WCAG 3.1.2: Language of Parts
A French quotation read aloud with English pronunciation rules is noise, not language. When a passage or phrase switches to a different language from the rest of the page, that passage must declare its own language in code — in HTML, a lang attribute on the element that wraps it — so screen readers can switch voices and pronounce it correctly.
The success criterion, in full
The human language of each passage or phrase in the content can be programmatically determined except for proper names, technical terms, words of indeterminate language, and words or phrases that have become part of the vernacular of the immediately surrounding text.
The rule is broad — each passage or phrase — but the four built-in exceptions do a lot of work: proper names, technical terms, words of indeterminate language, and loanwords absorbed into the surrounding language never need their own markup.
Why language markers matter
Screen readers do not detect language by reading the words — they trust the markup. The page-level lang attribute (covered by 3.1.1 Language of Page) selects the default voice and pronunciation rules. When the text switches language and the markup says nothing, the screen reader keeps applying the default rules — so “Guten Morgen, wie geht es Ihnen?” comes out as a garbled string of English-sounding syllables that even a fluent German speaker cannot recognize.
With a correct inline marker, the experience is seamless: the synthesizer switches to a German voice for the quoted sentence and back again afterwards. The same declaration helps braille devices select the right contraction tables for each passage, lets browsers and translation tools segment the content correctly, and helps user agents choose fonts appropriate to the script.
The people who benefit most are screen reader users who read multilingual content — quotations, glossaries, language-learning materials, bilingual legal notices, navigation to translated versions of a site — and users of braille displays and text-to-speech tools in any of those contexts.
The four exceptions
Not every foreign-looking word needs markup. The criterion itself excludes four categories — mark up genuine passages and phrases in another language, and leave these alone:
Proper names
People and place names keep their native form everywhere: 'François Truffaut', 'München', 'São Paulo' in an English sentence need no lang attribute.
Technical terms
Terms of art used unchanged across languages: 'Homo sapiens', 'habeas corpus', 'in vitro'. They are read as part of the surrounding text.
Words of indeterminate language
Coined product names, nonsense words, or strings that belong to no identifiable human language have no language to declare.
Vernacular loanwords
Words absorbed into the surrounding language — 'rendezvous', 'ad hoc', 'et cetera', 'kindergarten' in English. If it is in the dictionary of the surrounding language, it needs no markup.
The practical test: has the word or phrase become part of the surrounding language, or is the author deliberately switching languages? “She said c’est la vieand moved on” is borderline vernacular; a full French sentence quoted in an article is unambiguously a language change and must be marked.
Pass and fail examples
French quotation wrapped with lang="fr"(passes)
An English article quotes Voltaire in French inside <blockquote lang="fr">. Screen readers switch to a French voice for the quote. Passes.
Language switcher with per-link lang(passes)
A navigation offering 'Deutsch', 'Français', and 'Español' marks each link with its own lang attribute, so each language name is pronounced in that language. Passes.
Proper names left unmarked(passes)
An English biography mentions 'Ludwig van Beethoven' and 'Wien' without markup. Proper names are excepted. Passes.
German paragraph with no lang attribute(fails)
A bilingual product page alternates English and German paragraphs but declares only lang="en" on <html>. The German paragraphs are read with English pronunciation. Fails.
lang on the wrong element(fails)
A Spanish testimonial is wrapped in a div, but lang="es" was placed on a sibling element rather than the one containing the text. The passage's language cannot be programmatically determined. Fails.
Code examples
Inline phrases and block quotations
Put the lang attribute on the element that wraps exactly the foreign-language text — a <span> for an inline phrase, a <blockquote> or <p> for a block. Use valid BCP 47 codes.
<!-- ✗ Language changes with no markup: read with English rules -->
<p>As the proverb goes, Übung macht den Meister.</p>
<blockquote>
<p>Rien ne sert de courir; il faut partir à point.</p>
</blockquote>
<!-- ✓ Each passage declares its own language -->
<p>
As the proverb goes,
<span lang="de">Übung macht den Meister</span>.
</p>
<blockquote lang="fr">
<p>Rien ne sert de courir; il faut partir à point.</p>
<footer>— Jean de La Fontaine</footer>
</blockquote>A language switcher, done right
Each language name is written in its own language, so each link gets its own lang. Adding hreflang describes the destination document, but only lang affects how the link text itself is pronounced.
<!-- ✗ 'Deutsch' and 'Français' read with English phonetics -->
<nav aria-label="Language">
<a href="/de/">Deutsch</a>
<a href="/fr/">Français</a>
<a href="/es/">Español</a>
</nav>
<!-- ✓ Each language name pronounced in its own language -->
<nav aria-label="Language">
<a href="/de/" lang="de" hreflang="de">Deutsch</a>
<a href="/fr/" lang="fr" hreflang="fr">Français</a>
<a href="/es/" lang="es" hreflang="es">Español</a>
</nav>Nested languages inherit — and override
lang cascades: everything inside an element inherits its language until a descendant overrides it. That makes mixed-language structures straightforward.
<html lang="en">
<body>
<p>The review of the German edition was glowing:</p>
<blockquote lang="de">
<p>
Ein Meisterwerk — obwohl der Titel
<span lang="en">"The Silent Patient"</span>
unübersetzt blieb.
</p>
</blockquote>
<!-- English page → German quote → English title inside it.
Each level is announced with the correct voice. -->
</body>
</html>Common failures
- Quoting a full sentence or paragraph in another language with no lang attribute on any wrapping element — the single most common failure.
- Language-switcher links ('Deutsch', 'Français', '日本語') without per-link lang attributes, so every language name is mangled by the default voice.
- Invalid or made-up language codes: lang="gr" for German (it should be de; gr is not Greek either — that is el), lang="english", or an empty lang="" on a passage.
- Putting the lang attribute on the wrong element — a parent that also contains default-language text, or a sibling — instead of the element wrapping exactly the foreign passage.
- Foreign-language accessible names: an aria-label or alt text in another language on an element that does not carry a matching lang attribute.
- Over-marking: wrapping proper names, established loanwords, or technical terms in lang spans. This is not a conformance failure but causes needless voice-switching that makes listening worse.
How to test for 3.1.2
- 1
Read the page and list every language switch
Scan the content for passages, quotations, phrases, testimonials, or UI strings that are not in the page's default language. Include text exposed to assistive technology: alt text, aria-labels, and visually hidden text.
- 2
Inspect the markup for each switch
For every passage on the list, use the browser DevTools to confirm a valid BCP 47 lang attribute sits on the element wrapping that passage (or on an ancestor whose content is entirely in that language).
- 3
Apply the four exceptions
Strike proper names, technical terms, indeterminate words, and vernacular loanwords from your list — those need no markup. What remains must all be marked.
- 4
Listen with a screen reader
Read the page with NVDA, JAWS, or VoiceOver with automatic language switching enabled. A correctly marked passage is announced in the right voice; a garbled foreign passage in the default voice means a missing or wrong lang attribute.
- 5
Validate the codes
Check that every lang value is a well-formed BCP 47 tag — 'de', 'fr-CA', 'zh-Hans' — not a country code or a language name. An HTML validator or axe will catch malformed values, but not a valid code on the wrong passage.
Because the judgment calls — is this vernacular? is this a proper name? — are human ones, treat automated results as a starting point and verify by listening. Then work through the full WCAG 2.2 checklist.
Frequently asked questions
What does WCAG 3.1.2 Language of Parts require?
It requires that the human language of each passage or phrase in the content can be programmatically determined. In HTML that means adding a lang attribute to the element that wraps any text written in a language different from the page's default — for example <span lang="fr"> around a French quotation inside an English article. Four things are excepted: proper names, technical terms, words of indeterminate language, and words or phrases that have become part of the vernacular of the surrounding text. It is a Level AA criterion introduced in WCAG 2.0 and unchanged in 2.1 and 2.2.
How is 3.1.2 different from 3.1.1 Language of Page?
3.1.1 (Level A) sets the one default language for the whole document, via lang on the <html> element. 3.1.2 (Level AA) covers the exceptions inside the page: any passage or phrase written in a different language from that default must carry its own lang attribute. Think of 3.1.1 as the page-wide rule and 3.1.2 as the per-passage overrides. You need both: a correctly declared page language, and correctly marked switches wherever the language changes.
Why do inline language changes matter for screen readers?
Screen readers pick a speech synthesizer and pronunciation rules based on the declared language. If a German sentence sits inside an English page with no lang="de" marker, the screen reader reads the German words using English phonetics, which typically renders them unintelligible. With the marker, the screen reader switches voices mid-sentence and pronounces the passage correctly. The declaration also helps braille translation software select the right contraction tables and helps browsers choose appropriate fonts and dictionaries.
What are the exceptions — which words do NOT need a lang attribute?
Four categories are excepted by the normative text. Proper names: 'München' or 'François Truffaut' in an English sentence need no markup. Technical terms: terms of art like 'Homo sapiens' or 'habeas corpus' that are conventionally used unchanged. Words of indeterminate language: made-up or ambiguous words that belong to no identifiable language. And loanwords or phrases that have become part of the vernacular of the surrounding language: 'rendezvous', 'et cetera', 'ad hoc' in English are simply English now. If a word appears in a dictionary of the surrounding language, it does not need its own lang.
Does 3.1.2 apply to attributes and hidden text too, or only visible passages?
It applies to content that is read by assistive technology, which includes more than what is visible: alt text, aria-label values, visually hidden text, and title attributes are all announced by screen readers. The lang attribute applies to an element and everything in it, including its own attribute values — so a French aria-label on an element inside otherwise-English content needs that element (or a wrapper) to carry lang="fr". In practice, keep accessible names in the language of the surrounding content wherever possible; it avoids the problem entirely.
Can automated tools test 3.1.2?
Only partially. Automated checkers can flag syntactically invalid lang values (like lang="english") and some can run language detection to guess where a passage differs from the declared page language — but detection is unreliable for short phrases, names, and technical vocabulary. What no tool can fully judge is whether an unmarked phrase is a genuine language change or falls under the proper-name/vernacular exceptions. Reliable testing means reading the content, spotting language switches, and listening to them with a screen reader.
Related Success Criteria
The default human language of each page can be programmatically determined.
A mechanism is available for identifying specific definitions of words.
A mechanism for identifying the expanded form of abbreviations is available.
Text requires reading ability no higher than lower secondary education level.
A mechanism is available for identifying pronunciation of words.