On each web page, is the language code of each change of language valid and relevant?

A screen reader chooses its speech engine based on the language declared in the code. Set lang="fr" on a passage in English, and NVDA will read « Hello, world » with a French voice. Result: unintelligible. Criterion 8.7 requires that language changes be signalled; criterion 8.8 requires that these signals be correct.

Two conditions must be met for each lang attribute on a language change. The code must be valid: compliant with BCP 47, whose base is ISO 639-1 (two-letter codes such as fr, en, de, es). lang="french" or lang="anglais" are invalid codes; they are full language names, not standardized identifiers. The code must be relevant: lang="de" on German text, not on Spanish text.

Invalid code and irrelevant code are two distinct errors. A lang="fr" on English text is a valid but irrelevant code. A lang="english" on English text is a relevant but invalid code. Both cause test 8.8.1 to fail.

Un test to check the validity of language codes used

Validity and relevance of lang code on language changes

Take each passage of text identified during test 8.7.1 (text in a language different from the page's default language, carrying a lang or xml:lang attribute).

  1. Verify that the language code is valid: it must comply with BCP 47. Valid examples: fr, en, de, zh, pt-BR, ar. Invalid examples: french, german, eng-uk (malformed).
  2. Verify that the language code is relevant: the value must match the actual language of the passage. Text in Japanese marked lang="zh" (Chinese) is not relevant.
  3. If both conditions are met for all identified passages, the test is validated. A single invalid or irrelevant passage causes the criterion to fail.

Examples

❌ Non-compliant : Invalid language code: language name instead of standardized code

<p>For more information, consult our <span lang="english">knowledge base</span>.</p>

lang="english" is not a valid BCP 47 code. Screen readers do not recognize this format and may ignore the declaration. The term « knowledge base » will be read with the default French voice. The correct code is lang="en".

❌ Non-compliant : Valid code but not relevant: wrong language declared

<blockquote lang="fr">
  <p>Das Pferd frisst keinen Gurkensalat.</p>
</blockquote>

This text is in German, but the attribute declares French. JAWS and NVDA will choose the French voice to read German, producing systematically incorrect pronunciation. This is a more insidious error than the absence of lang, because it actively misleads assistive technologies.

✅ Compliant : Valid and relevant code with regional subtag

<p>Our policy is also available in English:
  <span lang="en-GB">This privacy policy is governed by English law.</span>
</p>

lang="en-GB" is a valid BCP 47 code (primary code en and regional subtag GB) and relevant because the text is indeed in British English. The regional subtag is optional but correct here. lang="en" alone would also satisfy the criterion.

Tips and pitfalls

⚠️ Copy-pasting a component without checking the lang attribute

This is the most common error in audits. A developer copies an HTML block with its lang="fr" and integrates it into an English section. The code remains valid (ISO 639-1), but it has become irrelevant. Reusable components like quotation blocks and multilingual editorial sections are particularly exposed.

⚠️ Full language names instead of codes

You regularly encounter lang="french", lang="german", lang="arabic" in legacy codebases. These are language names, not BCP 47 codes. The correct values are fr, de, ar. Criterion 8.8 considers these values invalid even if the intended language is correct, which can be surprising on a first audit.

💡 Quickly audit all lang attributes on the page

In the DevTools console, run document.querySelectorAll('[lang]') to list all elements carrying a lang attribute. Check each value: at least two letters, compliant with BCP 47, and matching the language of the visible content. Includdy automatically flags unrecognized codes.

⚠️ Regional subtags: mandatory or optional?

The primary code is sufficient to satisfy criterion 8.8. lang="en" is valid and relevant for English, whether British or American. The subtags en-GB or en-US are valid and may refine pronunciation according to available voices, but their absence is not a non-compliance.

⚠️ Technical terms, proper nouns and indeterminate words

These elements are outside the scope of criterion 8.7 and therefore 8.8: you do not need to mark « JavaScript » or « Paris » in French text. However, if you choose to mark them anyway, the code applied must be valid and relevant or it will cause 8.8 to fail.

Frequently asked questions

What language codes are valid according to HTML and RGAA specifications?

Codes compliant with BCP 47, whose base is ISO 639-1 (two letters: fr, en, de, ja, ar, zh). Three-letter ISO 639-2 and 639-3 codes are valid for languages without a two-letter equivalent. Well-formed regional subtags (en-GB, pt-BR, zh-Hant) are also accepted. A full language name (french, german) is systematically invalid.

How does an incorrect lang attribute differ from an absent lang in RGAA?

Yes, in most cases. Without lang, the screen reader inherits the page language and pronounces the text with that voice, often an approximate result but not catastrophic. With lang="fr" on English text, it actively applies French phonetic rules to English content, producing systematically incorrect pronunciation. The relevance error actively misleads assistive technologies.

How do RGAA criteria 8.7 and 8.8 differ on page language?

Criterion 8.7 verifies the presence of marking: is a language change signalled in the source code? Criterion 8.8 verifies the quality of that marking: is the code used valid (BCP 47) and relevant (correct language)? A passage without lang fails 8.7 and 8.8 is not applicable. A passage with lang="french" passes 8.7 but fails 8.8.

How can I automatically detect invalid lang attributes on a web page?

Includdy and the W3C validator (validator.w3.org) flag lang values not recognized in BCP 47. They cover obvious cases: language names, malformed codes, empty values. Relevance verification, that is, confirming that the code matches the actual language of the content, remains a manual operation.

How do I correctly mark an isolated foreign word with the lang attribute in RGAA?

No, only on passages in a language different from the page's default language, as required by criterion 8.7. An isolated technical word (cache, widget, open source) generally does not need marking. As soon as it is an expression or passage written in another language, marking becomes necessary and the code must be valid and relevant under criterion 8.8.

References