accessibility
HTML lang for screen readers
MetricSpot reads the `lang` attribute on `<html>`. Without it, screen readers pick the wrong pronunciation voice and assistive tech can't switch languages.
What this check does
Reads the lang attribute on the root <html> element. The value must be a valid BCP 47 language tag (en, en-GB, es, pt-BR, etc.).
Why it matters
Screen readers like NVDA, JAWS, and VoiceOver use this attribute to pick the correct voice synthesizer and pronunciation. A missing lang reads English content with whichever voice the user has set as default — often Spanish or German, producing gibberish. WCAG 3.1.1 makes this a Level A requirement; the EU Accessibility Act (in force since June 2025) treats missing lang as a compliance defect.
Search engines also lean on it for language detection alongside hreflang and content signals.
How to fix it
Set the attribute on the root element:
<html lang="en">
For regional variants, use a BCP 47 subtag:
<html lang="en-US"> <!-- US English -->
<html lang="pt-BR"> <!-- Brazilian Portuguese -->
<html lang="zh-Hant"><!-- Traditional Chinese -->
Astro: set in src/layouts/BaseLayout.astro:
<html lang={Astro.currentLocale ?? "en"}>
Next.js (App Router): in app/layout.tsx:
export default function RootLayout({ children }: { children: React.ReactNode }) {
return <html lang="en"><body>{children}</body></html>;
}
WordPress: lives in header.php:
<html <?php language_attributes(); ?>>
language_attributes() already emits lang="en-US" based on Settings → General → Site Language. Don’t hardcode over it.
Multi-language pages: add lang on the wrapping element when content switches mid-page:
<p>The French call it <span lang="fr">la mode</span>.</p>
This is what makes <span lang="fr"> read with a French voice instead of mangling the accent.
If you also serve multiple locales, pair this with hreflang tags so Google sends the right locale to the right user.
Frequently asked questions
What’s the difference between lang and xml:lang?
lang is the HTML attribute; xml:lang is its XHTML/XML equivalent. For HTML5 documents, just use lang. For polyglot documents (rare today), set both to the same value.
Can I leave lang off if I detect the language with JavaScript?
No. Screen readers parse the HTML before JS runs, and many assistive tech users disable JS entirely. The attribute must be in the static HTML.
Why does Lighthouse flag lang="" as invalid?
An empty string isn’t a valid BCP 47 tag. Either set a real language code or remove the attribute (worse — the check still fails). The same applies to lang="default" or other placeholder values some CMS themes ship with.
Sources
Last updated 2026-05-11