3.1.2 Language of Parts

WCAG 2.2 · 3.1.2 AA Understandable

What it requires

When a phrase or passage on a page is written in a language other than the page's default language, that change of language must be identified in the markup. In HTML this means adding a lang attribute (with a valid BCP 47 language tag) to the element that wraps the foreign-language content. This lets assistive technology — chiefly screen readers — switch to the correct pronunciation rules and voice for that snippet.

There are two practical exceptions: individual proper names, technical terms, words of indeterminate language, and words that have become part of the surrounding language do not need to be marked. The overall page language is handled separately by 3.1.1 Language of Page; 3.1.2 covers the parts that differ from it.

When language changes go unmarked, the people most affected are:

  • Blind and low-vision screen-reader users — the synthesizer keeps the page's default language, so a French quotation read with English phonetics becomes garbled and unintelligible.
  • People with reading or cognitive disabilities who rely on text-to-speech to follow content, where mispronunciation breaks comprehension.
  • Braille display users, since correct contracted braille depends on knowing the language of the text.

How to detect it

Ways to check for Language of Parts
Check What to look for
Manual review Scan the content for words, phrases, or passages in another language and confirm each wrapping element carries a matching lang attribute.
Screen reader Listen with NVDA, JAWS, or VoiceOver: foreign passages should switch voice or pronunciation. English phonetics on non-English text signals a failure.
Tag validity Verify each lang value is a valid BCP 47 tag (e.g. fr, es-MX), not an invented or empty code.
Automated tools axe and similar tools can flag invalid lang values, but cannot tell that a passage is in another language — detection is largely manual.

How to fix it

  1. Identify each phrase or passage that differs from the page's default language.
  2. Wrap it in an element (such as span, blockquote, or p) and set its lang attribute to the correct BCP 47 tag.
  3. Leave isolated proper names and adopted words alone; mark genuine language changes.
  4. Re-test with a screen reader to confirm the pronunciation switches correctly.
<p>She ended every email with <span lang="fr">c'est la vie</span>.</p>

Copy-paste tests

Automated coverage

The axe-core rule valid-lang flags failures of this criterion. Run it through the axe DevTools browser extension or axe-core in CI. Automated tools only catch some failures — they can spot an invalid lang tag but cannot tell whether a passage is actually in another language.

Run this in the browser console

lang-parts-audit.js
// Read-only: surface every element that declares a lang change.
const pageLang = document.documentElement.lang || '(none)';
const parts = [...document.querySelectorAll('[lang]')].filter(el => el !== document.documentElement);
console.log('Page default lang:', pageLang, '—', parts.length, 'inner lang declarations');
console.table(parts.map(el => ({
  tag: el.tagName.toLowerCase(),
  lang: el.getAttribute('lang'),
  text: el.textContent.trim().slice(0, 60)
})));
parts.forEach(el => { el.style.outline = '2px solid hotpink'; });

What to check manually: read the page and confirm every foreign-language phrase actually carries a lang attribute (the script cannot detect an unmarked passage), and verify each declared tag is a valid BCP 47 code that matches the real language of the text.