How to Fix Missing or Incorrect Document Language
The document language tells browsers and assistive technologies which language the page content is written in. Without it, screen readers cannot select the correct voice profile and pronunciation rules, which makes the content difficult or impossible to understand for users who rely on text-to-speech. Search engines also use the language declaration to serve pages to the right audience.
Why Document Language Matters
Screen readers maintain separate voice profiles and pronunciation dictionaries for each language. When a screen reader encounters a page without a declared language, it falls back to the user's default language setting. If the page is in French but the user's screen reader defaults to English, every word will be mispronounced. The page becomes unintelligible.
Beyond screen readers, the lang attribute affects browser behavior for hyphenation, spell checking, and quotation mark styling through CSS. Omitting it degrades the experience for everyone.
WCAG Success Criteria
SC 3.1.1 Language of Page (Level A) requires that the default human language of each web page can be programmatically determined. This is achieved by setting the lang attribute on the <html> element.
SC 3.1.2 Language of Parts (Level AA) requires that the language of each passage or phrase in the content can be programmatically determined, except for proper names, technical terms, and words that have become part of the surrounding language. This means using the lang attribute on inline elements when you include text in a different language.
Axe-Core Rules
Automated accessibility testing with axe-core checks for four related rules:
- html-has-lang — the
<html>element must have alangattribute. Fails when the attribute is missing entirely. - html-lang-valid — the
langattribute value must be a valid BCP 47 language tag. Fails for empty values, misspelled codes, or made-up tags. - html-xml-lang-mismatch — when both
langandxml:langare present on the<html>element, their primary language subtags must match. Fails when they specify different languages. - valid-lang — the
langattribute on any element in the page must use a valid BCP 47 language tag. Catches incorrect language declarations on inline elements.
The Fix: Add lang to the html Element
The most common fix is simply adding the lang attribute to your opening <html> tag. Before:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My Website</title>
</head>
<body>...</body>
</html>
After:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Website</title>
</head>
<body>...</body>
</html>
That single attribute addition resolves both html-has-lang and html-lang-valid when using a correct language code.
BCP 47 Language Tags
The lang attribute requires a valid BCP 47 language tag. At its simplest, this is a two-letter ISO 639-1 code. You can optionally add a region subtag for locale-specific variants.
| Language | Code | With Region |
|---|---|---|
| English | en | en-US, en-GB |
| Danish | da | da-DK |
| German | de | de-DE, de-AT, de-CH |
| French | fr | fr-FR, fr-CA, fr-BE |
| Spanish | es | es-ES, es-MX |
| Italian | it | it-IT |
| Dutch | nl | nl-NL, nl-BE |
| Swedish | sv | sv-SE |
| Norwegian | nb / nn | nb-NO, nn-NO |
| Portuguese | pt | pt-BR, pt-PT |
| Japanese | ja | ja-JP |
| Chinese (Simplified) | zh | zh-CN, zh-Hans |
| Chinese (Traditional) | zh | zh-TW, zh-Hant |
| Korean | ko | ko-KR |
| Arabic | ar | ar-SA, ar-EG |
| Polish | pl | pl-PL |
| Finnish | fi | fi-FI |
Use the two-letter code when the content is not region-specific. Add the region subtag when pronunciation, spelling, or date formats differ between regions, such as en-US versus en-GB. Avoid invalid codes like lang="english" or lang="uk" (which is the code for Ukrainian, not United Kingdom English).
Mixed-Language Content
When a page contains text in a language different from the page's primary language, wrap that text in an element with its own lang attribute. This satisfies SC 3.1.2 and allows screen readers to switch voice profiles for the foreign-language passage.
Before (screen reader uses English pronunciation for the French text):
<p>The French term mise en place means everything in its place.</p>
After (screen reader switches to French voice for the phrase):
<p>The French term <span lang="fr">mise en place</span> means everything in its place.</p>
You do not need to mark up proper names, technical terms, or loanwords that have become part of the surrounding language (such as "café" or "kindergarten" in English).
xml:lang for XHTML
If you serve your pages as XHTML (with the application/xhtml+xml content type), you must use xml:lang instead of or in addition to lang. For maximum compatibility, set both:
<html xmlns="http://www.w3.org/1999/xhtml" lang="da" xml:lang="da">
When both attributes are present, their primary language subtags must match. Setting lang="en" and xml:lang="de" will trigger the html-xml-lang-mismatch rule. Most modern websites use HTML5 served as text/html and only need the lang attribute.
CMS-Specific Settings
WordPress sets the language automatically based on your site language in Settings > General. If it is set incorrectly, change the "Site Language" dropdown. WordPress outputs the lang attribute via the language_attributes() function in header.php. If your theme is missing this function call, add it:
<html <?php language_attributes(); ?>>
Shopify uses the {{ request.locale.iso_code }} Liquid variable. In your theme.liquid layout file, ensure the html tag looks like:
<html lang="{{ request.locale.iso_code }}">
Squarespace, Wix, and similar hosted platforms typically set the language based on your site settings. Check your site's language or region settings in the platform's dashboard. If the output is incorrect, contact the platform's support or look for a language override setting.
Static site generators (Next.js, Gatsby, Hugo, Jekyll) require you to set the language in the HTML template or configuration. For Next.js, set it in next.config.js:
module.exports = {
i18n: {
defaultLocale: 'en',
locales: ['en', 'da', 'de'],
},
};
Single-Page Applications
In SPAs built with React, Vue, Angular, or similar frameworks, the initial HTML document includes the lang attribute, but you must also update it dynamically when the language changes (for example, when the user switches locale).
Set the language on page load or route change using JavaScript:
document.documentElement.lang = 'da';
In React with react-router, update the language in a route change handler or effect:
useEffect(() => {
document.documentElement.lang = currentLocale;
}, [currentLocale]);
In Vue, use a watcher or router guard:
router.afterEach((to) => {
document.documentElement.lang = to.params.locale || 'en';
});
Multilingual Sites
On multilingual sites, the lang attribute must reflect the actual language of the current page, not a hardcoded default. Common approaches:
- Set
langdynamically based on the URL path, subdomain, or query parameter that identifies the current language. - Use
hreflanglink elements in the<head>to indicate alternate language versions. This helps search engines but does not replace thelangattribute on<html>. - Ensure translated pages update the
langvalue. A German translation served withlang="en"fails the intent of SC 3.1.1 even though the attribute is technically present and valid. - For pages with substantial bilingual content (such as a language-learning site), set the
langon<html>to the primary language and mark up the secondary language with inlinelangattributes.
Testing
Verify your fix with these approaches:
- View source — open your page source and confirm the
<html>tag has a validlangattribute. For SPAs, inspect the live DOM in DevTools instead of viewing the static source. - Passiro — run a scan to check that
html-has-lang,html-lang-valid,html-xml-lang-mismatch, andvalid-langall pass. - axe DevTools — the browser extension flags missing or invalid language attributes in the issues panel.
- Screen reader testing — enable a screen reader (VoiceOver, NVDA, JAWS) and listen for correct pronunciation. If the voice sounds wrong, the language declaration is likely missing or incorrect.
- W3C Validator — the HTML validator at validator.w3.org warns about missing
langattributes.
This is one of the simplest and highest-impact accessibility fixes. A single attribute on the <html> element resolves a Level A requirement and immediately improves the experience for every screen reader user visiting your site.
Er din website tilgængelig?
Scan din website gratis og få din WCAG-score på få minutter.
Scan dit site gratis