squirrelscan
GitHub

html lang: valid values and what a missing one breaks

Without a lang attribute a screen reader guesses the pronunciation, often wrongly. squirrel checks the html element on every page.

What the lang attribute is

lang on <html> declares what language the document is written in, as a BCP 47 tag. A screen reader uses it to choose a voice and a set of pronunciation rules. Read English with a French synthesiser and most of it is unintelligible.

The tag has a primary subtag, en, optionally followed by script and region subtags, en-GB or zh-Hans-CN. The primary subtag is the part that matters for pronunciation; the region subtag usually selects an accent.

What squirrel checks

Two check names, at rule severity error. Only one runs per page.

  • html-has-lang fails when <html> has no lang attribute, and also when it has lang="", since the rule tests the attribute for truthiness. Report message: HTML element missing lang attribute, with the expected value lang="en" or appropriate language code. Nothing else is checked.
  • html-lang-valid fails when the value is whitespace only, or when its primary subtag is neither one of the 190 ISO 639-1 codes the rule knows nor a plain two or three letter sequence. Report message: Invalid lang attribute: empty value or Invalid lang attribute: invalid primary language 'english', with the expected value Valid BCP 47 language tag (e.g., 'en', 'en-US', 'es').
  • html-lang-valid passes with Valid lang attribute: "en-GB".

Two limits follow from that shape check. Any two or three lowercase letters pass, so an invented code such as qq is accepted. And script and region subtags are not validated at all, so en-ZZ passes.

How to fix it

<html lang="en-GB">

Set it on the <html> element of every page, including error pages and pages rendered by a framework’s fallback layout. A region subtag is worth adding when the accent matters, and harmless when it does not.

For a page whose main content is in another language, change this attribute rather than adding lang further down. Marking individual passages is what a11y/valid-lang covers.

Rule IDa11y/html-lang-valid
CategoryAccessibility
ScopePer-page
Severityerror
Weight7/10

Enable / disable

Disable this rule

[rules]
disable = ["a11y/html-lang-valid"]

Disable all Accessibility rules

[rules]
disable = ["a11y/*"]

Enable only this rule

[rules]
enable = ["a11y/html-lang-valid"]

enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.

Accessibility findings ship in every audit next to the SEO, performance and agent experience rules. See Website security scan with AI for how an agent works through a report.

References

Check your site

Run squirrel audit https://example.com and open the Accessibility section of the report. A missing attribute and an invalid value are reported as different checks. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.

Type to search…

↑↓ navigate↵ openesc close