# The lang attribute on <html> must have a valid value.

> Canonical HTML version: https://rocketvalidator.com/accessibility-validation/accesslint/0.16/readable/html-lang-valid
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The `lang` attribute on the `<html>` element tells browsers and assistive technologies what language the page is written in. When this attribute contains an invalid value, screen readers cannot determine the correct pronunciation rules to apply. A screen reader set to read English content will mispronounce words if it cannot identify the language, and one that supports multiple languages will fail to switch to the appropriate voice or pronunciation engine. The result is garbled or unintelligible speech output for screen reader users.

This rule checks that the `lang` attribute uses a valid language tag as defined by BCP 47 (RFC 5646). A valid tag starts with a known primary language subtag, which is a 2-letter (ISO 639-1) or 3-letter (ISO 639-2) code. However, not all 3-letter codes are well supported by assistive technologies. Two-letter codes like `en`, `fr`, `de`, and `zh` are the most reliable choice. An optional region subtag can follow, separated by a hyphen: `en-US`, `pt-BR`, `zh-Hans`.

Common mistakes include typos in the language code (like `em` instead of `en`), using nonsense strings, using symbols or numbers, or using ISO 639-2 three-letter codes (like `eng` instead of `en`) that many assistive technologies do not recognize. Grandfathered tags such as `i-lux` also lack support in most screen readers and should be replaced with their modern equivalents.

## Related WCAG success criteria

This rule maps to [WCAG 2 Success Criterion 3.1.1: Language of Page](https://www.w3.org/WAI/WCAG22/Understanding/language-of-page.html) (Level A). This criterion requires that the default human language of each web page can be programmatically determined. An invalid `lang` value means assistive technology cannot determine the language, so the criterion is not satisfied.

## How to fix it

1. Open the HTML document and find the `<html>` element.
2. Check the value of its `lang` attribute.
3. Replace the value with a valid BCP 47 primary language subtag. Use a 2-letter code whenever one exists for the language (e.g., `en` for English, `fr` for French, `de` for German, `ja` for Japanese).
4. Optionally append a region subtag if the content targets a specific locale (e.g., `en-GB`, `es-MX`).
5. The value is case-insensitive, so `en`, `EN`, and `En` are all valid.

If the page currently uses a 3-letter ISO 639-2 code like `eng`, replace it with the corresponding 2-letter code `en`. If it uses a grandfathered tag like `i-lux`, replace it with the modern equivalent (`lb` for Luxembourgish).

This fix is mechanical: identify the invalid value and replace it with the correct language code. No structural changes to the page are needed.

## Examples

### Invalid lang values

A typo in the language code (`em` instead of `en`):

```html
<html lang="em-US">
  <head>
    <title>My page</title>
  </head>
  <body>
    <p>Hello world</p>
  </body>
</html>
```

A nonsense value with symbols:

```html
<html lang="#1">
  <head>
    <title>My page</title>
  </head>
  <body>
    <p>Hello world</p>
  </body>
</html>
```

A 3-letter ISO 639-2 code that most assistive technologies do not recognize as a primary language subtag:

```html
<html lang="eng">
  <head>
    <title>My page</title>
  </head>
  <body>
    <p>Hello world</p>
  </body>
</html>
```

### Valid lang values

A simple 2-letter language code:

```html
<html lang="en">
  <head>
    <title>My page</title>
  </head>
  <body>
    <p>Hello world</p>
  </body>
</html>
```

A language code with a region subtag:

```html
<html lang="en-US">
  <head>
    <title>My page</title>
  </head>
  <body>
    <p>Hello world</p>
  </body>
</html>
```

A case variation (uppercase is equally valid):

```html
<html lang="FR">
  <head>
    <title>My page</title>
  </head>
  <body>
    <p>Bonjour le monde</p>
  </body>
</html>
```
