Search topics
Passages in another language read with the wrong voice
A product page shows a customer review in French and a language switcher, but neither carries its own lang, so a screen reader reads both with English pronunciation.
<p class="review-text">Parfaite pour le café…</p> The problem
Screen reader and braille users get passages in another language read with the page's pronunciation rules, which can make them impossible to follow.
An outdoor shop sells an enamel camping mug, and its English product page lists the reviews customers have left. Most are in English; one, from a customer in Lyon, is in French: "Parfaite pour le café du matin au camping." A screen reader user reads the reviews to decide whether to buy. The English ones are fine. The French one comes out as "par-FATE poor lee kaff-AY doo MAT-in aw CAMP-ing", French words with English sounds, and they can't make it out, even though they read French. At the bottom of the page, the language switcher offers "Français", "Deutsch" and "Español", each read with the same English voice.
The page is marked lang="en", which is right for the page, and every element inside it inherits that language unless it says otherwise. The review is rendered from the shop's reviews feed, which knows the review was written in French, but the template never writes that out, so the review inherits English. The switcher's links carry hreflang="fr", which says what language the page they lead to is in, not what language their own text is in. Screen readers, read-aloud tools and braille translators take the language of each piece of text from lang, so they read all of it as English. WCAG 3.1.2 asks that the human language of each passage or phrase can be programmatically determined; here the French review and the three language names say they are English.
The failure follows the content, not the template: an English page looks and sounds right until a customer writes in another language, which a team testing with its own reviews may never see. Browsers can use lang too, to choose fonts, hyphenation and spell checking, and to decide what to offer to translate, so a passage marked with the wrong language can also be drawn and hyphenated wrongly.
3 of 10 groups affected
- No vision (affected)
- Low vision (affected)
- Colour vision (not affected)
- No hearing (not affected)
- Hard of hearing (not affected)
- No speech (not affected)
- Motor (not affected)
- Reach, strength (not affected)
- Cognitive (affected)
- Seizures (not affected)
- Without vision Screen readers pick a voice and pronunciation rules from lang. A French review with no lang of its own is read with English rules, and a braille display can apply English contractions to French words.
- Limited language, cognitive and learning abilities People who listen to text with a read-aloud tool to help them read hear the review garbled, and can't tell whether it is praise or a complaint.
- Limited vision People who use a screen reader or browser read-aloud alongside magnification hear the same wrong pronunciation.
axe's valid-lang rule checks the lang values a page has: lang="francais" is reported, lang="fr" passes. A passage with no lang at all is invisible to it, which is the usual form of this failure. EaseWeb's audit reports a language switcher whose language names have no lang of their own, and sends text in another writing system for review, such as a Japanese sentence on an English page or an English one on a Japanese page. A French review on an English page uses the same letters as the text around it, and no check here finds it. An AI tool can often guess what language a passage is in, but a person has to decide whether a word is a name, a technical term or a word borrowed into the page's language, none of which needs marking.
Try it
Listen to the French review and the language links.
Press Listen on each review and on the language links to hear them with the voice their lang picks, if your device has one; the panel shows the voice, roughly how it sounds, and where its language comes from.
Broken Can you fix this?
Enamel camping mug
- Light, tough, and keeps tea hot. Sam, Leeds
- Parfaite pour le café du matin au camping. Camille, Lyon
Press Listen on a review or on the language links.
The fix
Mark every passage in another language with its own lang, on the element that holds it, from the language it was written in.
- 1Every passage in another language carries its own valid lang, on the element that wraps it.
- 2Each name in a language switcher carries the lang of that language.
- 3Content that comes from data takes its lang from the language stored with it; hreflang never stands in for lang.
<html lang="en">…<h1>Enamel camping mug</h1>…<ul class="reviews"> <!-- rendered from the reviews feed --> <li> <p class="review-text">Light, tough, and keeps tea hot.</p> <p class="reviewer">Sam, Leeds</p> </li> <li> <p class="review-text">Parfaite pour le café du matin au camping.</p> <p class="reviewer">Camille, Lyon</p> </li></ul>…<footer> <nav aria-label="Language"> <a href="/en/" aria-current="true">English</a> <a href="/fr/" hreflang="fr">Français</a> <a href="/de/" hreflang="de">Deutsch</a> <a href="/es/" hreflang="es">Español</a> </nav></footer><html lang="en">…<h1>Enamel camping mug</h1>…<ul class="reviews"> <!-- each li takes the language stored with its review --> <li lang="en"> <p class="review-text">Light, tough, and keeps tea hot.</p> <p class="reviewer">Sam, Leeds</p> </li> <li lang="fr"> <p class="review-text">Parfaite pour le café du matin au camping.</p> <p class="reviewer">Camille, Lyon</p> </li></ul>…<footer> <nav aria-label="Language"> <a href="/en/" aria-current="true">English</a> <a href="/fr/" hreflang="fr" lang="fr">Français</a> <a href="/de/" hreflang="de" lang="de">Deutsch</a> <a href="/es/" hreflang="es" lang="es">Español</a> </nav></footer>The French review and the three language names inherit lang="en" from the page, so they are read with English pronunciation. hreflang describes where each link goes, and changes nothing about how its text is read.
Each review is wrapped in an element that carries the language stored with it, so the French one is read with French rules and the English text after it goes back to English. Every review gets its lang, the English ones too, so a review in English stays English on the French version of the page. Each language name carries the lang of the language it names, on the link itself, beside the hreflang that describes its target.
Put lang on the element that holds the whole passage: the review's list item, a blockquote, a p. For a few words inside a sentence, wrap them in a span lang="…". On a link or a button, put it on the element itself where you can: a control's name is worked out as plain text, and a lang on part of it can be lost on the way to assistive technology. A span with its own lang inside the link, as in W3C's own example, still meets 3.1.2. For the same reason, don't give a switcher link an aria-label such as "Switch to French": the name is then English, and a lang="fr" on the link would have it read with French rules. Let the visible language name be the name.
Content you don't write needs its language from somewhere. The ways to get it differ in how sure they are.
- The language the person used: a review posted from the French version of the site is most likely in French. Store that locale with the review when it is posted.
- Detection when the content arrives: a language detection library, or the browser's own detection where it has one, guesses well for a sentence or more and badly for two or three words. Store the result, and let a moderator correct it.
- A field on the form: ask the reviewer which language they wrote in, defaulting to the site's current language.
When the language can't be known, leave the passage without lang rather than guess, and treat that as a gap to close; a wrong lang fails just as a missing one does.
Some words in another language need no marking. WCAG 3.1.2 excludes proper names, technical terms, words of indeterminate language, and words that have become part of the surrounding language: "Camille" and "Lyon", "café" in an English sentence, a brand name. A test is whether the word would be said the same way by a speaker of the page's language. On a Japanese page, katakana loanwords are Japanese, but an English sentence such as a slogan or a review is a passage and needs lang="en". Marking Japanese text correctly also matters for how it looks: browsers can choose the shapes of Chinese characters from lang, so Japanese text inside a passage marked as Chinese can be drawn with Chinese forms.
Showing a review translated into the page's language is a separate feature. The translation is in the page's language and needs no lang; the original, wherever it is shown, still does.
The language of the page itself is 3.1.1, covered in page language set wrong, so screen readers mispronounce it. Use valid tags here as there: fr, de, es, zh-Hant, never french or jp.
Fixing this with an AI coding assistant? Get this guide as Markdown, or get every guide in your coding agent.
Verify the fix
5 checks, no mouse.
Test with: Screen reader
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat when content from a new source, or a new language, is added.
Limits
This is a starting pattern, not a guarantee for every application. Screen readers switch voices only when a voice for that language is installed, and some let the user turn automatic language switching off; that is outside your control, but the markup must still be right. Some screen readers also try to guess the language from the text itself; a guess is least reliable for a short passage in the same letters as the page, and not every reader makes one, so it doesn't replace lang. Whether a word needs marking can be a judgement call: check the passages that matter with someone who reads that language if you can.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
References
- WCAG Understanding: language-of-parts (opens in a new tab)
- WCAG Technique H58 (opens in a new tab)
- w3.org: qa-lang-why (opens in a new tab)
- w3.org: qa-choosing-language-tags (opens in a new tab)
- developer.mozilla.org: lang (opens in a new tab)
- developer.mozilla.org: a (opens in a new tab)
- dequeuniversity.com: valid-lang (opens in a new tab)
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.