WCAG 3.1.1: Language of Page
A screen reader cannot pronounce words correctly unless it knows what language they are in. This criterion asks one simple thing: declare the default language of the page in code. It is usually a single attribute — <html lang="en"> — yet it is one of the most commonly missed Level A requirements on the web.
The success criterion, in full
The default human language of each Web page can be programmatically determined.
“Programmatically determined” means available to assistive technology in code, not just visible to a sighted reader. For HTML, that is the lang attribute on the root <html> element. “Human language” means a spoken/written language like English or Japanese — not a programming language.
Why the page language matters
When a screen reader opens a page, one of the first things it looks for is the language. That value tells it which pronunciation engine and voice to load. Give it lang="fr" and it reads “bonjour” the way a French speaker would; leave the attribute off and an English-configured screen reader may read the same word with English phonetics — “bon-jower” — which a listener cannot understand.
This one attribute drives far more than a screen reader voice. Setting it correctly enables all of the following at once:
Screen reader pronunciation
Loads the correct phonetic rules and voice so text is read intelligibly instead of mangled.
Braille contraction tables
Refreshable braille displays pick the correct contraction rules, which differ by language.
Accurate machine translation
Browser translate features and tools detect the source language reliably instead of guessing.
Hyphenation & typography
Correct hyphenation, quotation marks, and script-appropriate fonts are selected by the browser.
The cost-to-benefit ratio here is extraordinary. Almost no other WCAG criterion is fixed by a single attribute that improves the experience for screen reader users, braille users, translation tools, and search engines all at the same time. It is the first thing to check on any audit.
Choosing the right language code
The value of the lang attribute must be a valid language tag from BCP 47 (defined by RFC 5646). In everyday use that means a two- or three-letter primary language subtag, optionally followed by a region or script subtag. You do not need to memorise the registry — a handful of patterns cover almost every page.
| Tag | Language | Notes |
|---|---|---|
en | English | Primary subtag alone is valid and sufficient. |
en-US | English (United States) | Region subtag is optional; helps pick a regional voice. |
en-GB | English (United Kingdom) | Use only if the page truly targets that region. |
es | Spanish | Bare primary subtag is fine for most Spanish content. |
fr | French | Applies French pronunciation across the page. |
pt-BR | Portuguese (Brazil) | Distinguishes Brazilian from European Portuguese. |
zh-Hans | Chinese (Simplified script) | Script subtag matters for Chinese. |
ar | Arabic | Pair with dir="rtl" for right-to-left layout. |
Two rules keep you safe: use lowercase for the primary language subtag, and never invent codes. lang="english", lang="us", and lang="gb" are all invalid. When unsure, the bare two-letter primary subtag — en, es, de — is always conformant.
Code examples
The basic, correct pattern
Put the lang attribute on the root <html> element. That single declaration covers the whole document.
<!-- ✗ No language declared — screen reader guesses -->
<html>
<head> ... </head>
<body> ... </body>
</html>
<!-- ✓ Default language set on the root element -->
<html lang="en">
<head> ... </head>
<body> ... </body>
</html>Match the code to the real content
A valid tag that describes the wrong language is still a failure. The most common version of this bug is a template hard-coded to en and reused for translated pages.
<!-- ✗ Page content is German, but lang says English -->
<html lang="en">
<body>
<h1>Willkommen auf unserer Website</h1>
</body>
</html>
<!-- ✓ lang matches the language the user actually reads -->
<html lang="de">
<body>
<h1>Willkommen auf unserer Website</h1>
</body>
</html>Right-to-left languages
For scripts that read right to left (Arabic, Hebrew, Persian), pair lang with the dir attribute so the layout direction is correct too.
<!-- ✓ Language and direction both declared -->
<html lang="ar" dir="rtl">
<body> ... </body>
</html>Setting it in frameworks and CMS platforms
The <html> tag is usually generated by a framework or template, so the fix often lives in one shared file rather than every page. A few common patterns:
// Next.js — app/layout.tsx (App Router)
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
// React (Vite/CRA) — set it in public/index.html
// <html lang="en"> ... </html>
// Angular — src/index.html
// <html lang="en"> ... </html>
// WordPress — theme header.php uses language_attributes()
// <html <?php language_attributes(); ?>>
// (fills lang from the Site Language setting in wp-admin)For multilingual sites, set the value dynamically from the active locale — for example <html lang={locale}> in Next.js internationalized routing — so a page served in French actually declares lang="fr" rather than inheriting a hard-coded default.
Common mistakes
- No lang attribute at all — the single most common failure, leaving the screen reader to guess from its own default settings.
- An invalid value such as lang="english", lang="us", or lang="en_US" (BCP 47 uses a hyphen, not an underscore).
- An empty attribute, lang="", which is treated as no valid language and fails the same way a missing one does.
- A hard-coded lang="en" reused on translated pages, so German or Spanish content is announced with English pronunciation.
- Putting lang only on the <body> or a wrapper <div> instead of the root <html> element, where user agents expect the page default.
- Confusing lang with the hreflang link attribute or an Open Graph locale — those are SEO/link hints and do not satisfy 3.1.1.
- Setting a region-only code like lang="US" with no primary language subtag, which is not a valid standalone tag.
- Assuming a <meta http-equiv="content-language"> tag counts — it does not satisfy 3.1.1; the lang attribute on <html> is required.
How to test for 3.1.1
- 1
Inspect the <html> element
Open DevTools, look at the root <html> tag, and confirm a lang attribute is present with a value. This is the fastest manual check and catches the most common failure — a completely missing attribute.
- 2
Validate the code against BCP 47
Confirm the value is a real language tag: lowercase primary subtag, hyphens (not underscores) between subtags, and no invented codes like 'english'. Run axe DevTools, Lighthouse, or WAVE — they flag both missing and malformed lang values automatically.
- 3
Confirm the code matches the content
This is the manual step tools cannot do. Read the page and verify the declared language is the language you actually see. A German page with lang="en" passes automated checks but fails the criterion.
- 4
Listen with a screen reader
Open the page in VoiceOver, NVDA, or JAWS and listen to the first few sentences. If the pronunciation sounds wrong for the visible language, the lang value is missing or incorrect. This is the most direct real-world confirmation.
- 5
Check every template and locale
On multilingual sites, test one page per language, not just the English home page. Translated pages served from a shared template are where hard-coded lang values most often slip through.
Because a missing or malformed lang attribute is machine-detectable, it belongs in every automated scan. Pair that with a quick manual language-match check, then work through the full WCAG 2.2 checklist.
Related success criteria
3.1.2 Language of Parts — AA
The per-passage companion to 3.1.1. Where 3.1.1 sets one default language for the page, 3.1.2 marks up individual phrases or quotations that are in a different language from that default.
1.3.1 Info and Relationships — A
The broader principle that information conveyed visually must also be available in code. Declaring the language programmatically is one instance of exposing meaning to assistive technology.
2.4.2 Page Titled — A
Another page-level requirement checked at the same time as language: the page needs a descriptive title, and its title and content should be in the declared language.
4.1.2 Name, Role, Value — A
Also about exposing information programmatically so assistive technology can present content correctly — here for controls, rather than the document’s language.
Browse every criterion in the WCAG Success Criteria hub or run a free scan with the accessibility testing tools.
Frequently asked questions
What does WCAG 3.1.1 Language of Page require?
It requires that the default human language of each web page can be programmatically determined. In practice this means setting a valid lang attribute on the <html> element, for example <html lang="en"> for English or <html lang="fr"> for French. The value must be a valid language tag from BCP 47 (the IETF standard that RFC 5646 defines). It is a Level A success criterion — the highest-priority conformance level — introduced in WCAG 2.0 and unchanged in WCAG 2.1 and 2.2.
Why does the lang attribute matter for accessibility?
Screen readers use the page language to load the correct pronunciation rules and voice. Without it, an English screen reader might read French text with English phonetics — rendering it unintelligible. The lang value also lets braille displays choose the right contraction tables, helps browsers offer accurate translation, selects the correct hyphenation and quotation-mark rules, and enables user agents to pick appropriate fonts for the script. A single correct attribute fixes all of these at once.
What is the difference between 3.1.1 Language of Page and 3.1.2 Language of Parts?
3.1.1 (Level A) is about the one default language for the whole page, declared on the <html> element. 3.1.2 Language of Parts (Level AA) covers passages or phrases inside the page that are in a different language from that default — a French quotation inside an English article, for example, which you mark with a lang attribute on the element wrapping just that phrase. Think of 3.1.1 as the page-wide default and 3.1.2 as the per-passage exceptions to it.
Is lang="en" enough, or do I need a region like en-US?
A primary language subtag such as lang="en" is sufficient to pass 3.1.1 — you do not need a region. Adding a region (lang="en-US", lang="en-GB", lang="pt-BR") is valid and can help assistive technology pick a regional voice or the right braille table, but it is optional. Do not invent region codes: use only registered BCP 47 subtags. When in doubt, the bare two-letter primary code is safe and conformant.
Does the lang attribute value have to match the visible content language?
Yes. Declaring lang="en" on a page that is actually written in Spanish still fails 3.1.1 in spirit and, more importantly, breaks pronunciation — the screen reader will apply English rules to Spanish text. The attribute must reflect the language a user actually reads on the page. A very common real-world bug is a template hard-coded to lang="en" that is reused for translated pages without updating the value.
How do automated accessibility tools test 3.1.1?
Automated checkers like axe, Lighthouse, and WAVE can reliably detect two of the three failure modes: a missing lang attribute, and a lang value that is not a well-formed BCP 47 tag (for example lang="english" or an empty lang=""). What they cannot judge is whether a valid code matches the actual content language — a page of German text with lang="en" passes the automated check but fails the criterion. That final match is a manual verification step.