lang on elements below html: validating every tag
A quoted passage marked with a bad lang tag is read in the wrong voice. squirrel validates every lang attribute except the one on html.
What lang on an element does
lang on <html> sets the document’s language. lang on any element below it overrides that for its subtree, which is how a French quotation inside an English article gets read with French pronunciation.
WCAG success criterion 3.1.2 Language of Parts, Level AA, asks for it wherever the language changes. An invalid tag is worse than none: it is exposed as given, and what a screen reader does with a tag it cannot resolve is up to the screen reader.
What squirrel checks
One check, valid-lang, at severity warning. It reads every [lang] element except <html>, which a11y/html-lang-valid handles on its own.
A value is accepted when its primary subtag, the part before the first hyphen, is one of the 190 ISO 639-1 codes the rule knows, or is any two or three lowercase letters.
- Warn with
N element(s) with invalid lang attribute. Items readspan#quote: lang="english", up to ten with a count of the rest. - Pass with
All lang attributes are valid, which requires the page to carrylangon more than one element. - Info with
No additional lang attributes found.
A page with lang only on <html> therefore reports info here, not pass. And because any two or three letter primary subtag is accepted by shape, an invented code such as qq passes. Region and script subtags are not validated at all.
How to fix it
<p>She ended with <span lang="fr">plus ca change</span>.</p>Use the short code, not the language’s name. lang="french" and lang="en-english" are both invalid, and both are common.
Mark the change where it happens, on the smallest element that contains the foreign text. Marking a whole article when one sentence changes makes the rest of it read wrongly.
| Rule ID | a11y/valid-lang |
| Category | Accessibility |
| Scope | Per-page |
| Severity | warning |
| Weight | 5/10 |
Enable / disable
Disable this rule
[rules]
disable = ["a11y/valid-lang"]Disable all Accessibility rules
[rules]
disable = ["a11y/*"]Enable only this rule
[rules]
enable = ["a11y/valid-lang"]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.
Related rules
- a11y/html-lang-valid: the document-level declaration on
<html>. - a11y/html-xml-lang-mismatch:
langandxml:langdisagreeing on that element. - i18n/lang-attribute: the same declaration checked for internationalization.
- i18n/hreflang: the language signals sent to search engines.
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
- The lang attribute, MDN
- Understanding SC 3.1.2 Language of Parts, W3C
- Tags for identifying languages, RFC 5646
Check your site
Run squirrel audit https://example.com and open the Accessibility section of the report. Each element is listed with the invalid value it carries. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.