# axe-core html-xml-lang-mismatch error lang xml lang mismatch failed - how to fix it

## TL;DR

When the [html] element carries both lang and xml:lang, their base languages must match. This mismatch almost always comes from a copy-pasted XHTML template or a CMS that sets one attribute while the theme sets the other. Pick the page's real language, set both attributes to it (or drop xml:lang entirely on HTML5 pages), and re-run the focused axe rule.

This violation is almost always inherited, not introduced: a layout template, a CMS theme, or a static-site generator default that nobody has touched in years. Fix it in the layout or theme once and every page inherits the correction. If different sections of the site genuinely serve different languages, the per-page lang should come from the content, and xml:lang should be dropped everywhere.

The verbatim error looks like this:

```text
axe-core 4.x
Rule: html-xml-lang-mismatch (moderate)
"HTML elements with lang and xml:lang must have the same base language"

Element: [html lang="en" xml:lang="fr"]
  Base languages differ: "en" vs "fr".
```

## Steps

1. Reproduce with the single rule:

```bash
npx @axe-core/cli https://example.com/ --rules html-xml-lang-mismatch,html-has-lang,html-lang-valid
```

Expected: the [html] element is flagged for the mismatch.

2. Determine the page's actual language from its content. That is the value both attributes should carry.

3. Fix the attributes. For HTML5, the simplest correct fix is to drop xml:lang:

```html
[html lang="en"]
```

If you serve true XHTML and need xml:lang, make them match: [html lang="en" xml:lang="en"].

4. Re-run the focused scan. Expected output: 0 violations across the three lang rules.

5. Verify with a screen reader that content is announced in the right language and accent.

6. Find where the attributes are set. Check the base layout, theme header, and any CMS language settings. The mismatch means two systems each set one attribute:

```bash
rg -l 'xml:lang' layouts/ themes/ src/
```

7. After fixing, crawl more than the homepage. Language settings often vary by section or content type, and a homepage-only check misses mismatches on translated or legacy sections.
## When to use

- Axe flags html-xml-lang-mismatch on the html element.
- A template migrated from XHTML still carries a stale xml:lang.
- A multilingual CMS sets lang per page while the theme hardcodes xml:lang.

## When not to use

- The page has no lang attribute at all (add lang; that is html-has-lang).
- The lang value itself is not a valid code (fix the code; that is html-lang-valid).
- A section of the page is in another language (mark that section with its own lang attribute; do not change the page-level attributes).

## Why it happens

Screen readers use the lang attribute to pick pronunciation rules. When lang says English and xml:lang says French, XML-aware tooling and HTML tooling disagree about how to read the page, and the user gets the wrong pronunciation. The mismatch is a leftover from the XHTML era and has no legitimate use on modern HTML pages.

xml:lang is a relic of XHTML, when pages were parsed as XML and the XML language attribute mattered. HTML5 parsing ignores xml:lang entirely, but axe still checks it when present because XML tooling (validators, some assistive tech pipelines) still reads it. The mismatch arises during migrations: the HTML was converted from XHTML, lang was updated over the years, and xml:lang fossilized.

## Edge cases

- Only the base language must match: lang="en-US" with xml:lang="en-GB" passes because the base ('en') agrees.
- The rule checks every element carrying both attributes, not just [html], though [html] is the overwhelmingly common case.
- Some static-site generators inject xml:lang via a layout default. Override it in the layout, not on every page.
- After the fix, run html-lang-valid too: a matching but invalid code just moves the failure to the next rule.
- XHTML served as application/xhtml+xml genuinely uses xml:lang, but almost nobody serves true XHTML anymore. Confirm your content type before keeping it.
- hreflang on links is unrelated to this rule. Do not 'fix' the mismatch by touching hreflang annotations.
- Automated translation plugins that rewrite lang per page can reintroduce the mismatch. Pin the fix in the layout, not per page.
- Some teams keep xml:lang 'for the XML sitemap tools'. Sitemap tooling reads hreflang and page content, not xml:lang on the html element.
- After the fix, validate a sample of pages with the W3C validator to confirm no other legacy XHTML attributes linger.
- If your site serves both HTML and XHTML from the same templates, split the layouts; one template cannot serve both correctly.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst__EQ7hKFZTaciN3HjymuAjg
