Skip to main content

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 a lang attribute. Fails when the attribute is missing entirely.
  • html-lang-valid — the lang attribute 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 lang and xml:lang are present on the <html> element, their primary language subtags must match. Fails when they specify different languages.
  • valid-lang — the lang attribute 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.

LanguageCodeWith Region
Englishenen-US, en-GB
Danishdada-DK
Germandede-DE, de-AT, de-CH
Frenchfrfr-FR, fr-CA, fr-BE
Spanisheses-ES, es-MX
Italianitit-IT
Dutchnlnl-NL, nl-BE
Swedishsvsv-SE
Norwegiannb / nnnb-NO, nn-NO
Portugueseptpt-BR, pt-PT
Japanesejaja-JP
Chinese (Simplified)zhzh-CN, zh-Hans
Chinese (Traditional)zhzh-TW, zh-Hant
Koreankoko-KR
Arabicarar-SA, ar-EG
Polishplpl-PL
Finnishfifi-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 lang dynamically based on the URL path, subdomain, or query parameter that identifies the current language.
  • Use hreflang link elements in the <head> to indicate alternate language versions. This helps search engines but does not replace the lang attribute on <html>.
  • Ensure translated pages update the lang value. A German translation served with lang="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 lang on <html> to the primary language and mark up the secondary language with inline lang attributes.

Testing

Verify your fix with these approaches:

  • View source — open your page source and confirm the <html> tag has a valid lang attribute. 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, and valid-lang all 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 lang attributes.

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.

Czy Twoja strona jest dostępna?

Przeskanuj swoją stronę za darmo i poznaj swój wynik WCAG w kilka minut.

Przeskanuj stronę za darmo