# HTML lang attribute is set

- **Pattern:** `ab-002527` (`site-health-check.accessibility-mobile.html-lang`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002527
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002527)

## Why it matters

Screen readers depend on the `lang` attribute to select the correct language engine for text-to-speech pronunciation. Without it, a screen reader may attempt to pronounce English content using French or Japanese pronunciation rules — producing incomprehensible audio for users who are blind or have low vision. WCAG 2.2 SC 3.1.1 (Language of Page) is a Level A requirement: the lowest, most foundational conformance level. Section 508 (2018 refresh) 504.2 also mandates language identification. A missing `lang` attribute is an automatic WCAG failure that makes the page non-compliant with accessibility law in the US, EU, and most jurisdictions.

## Severity rationale

Medium because the impact is targeted — screen reader users bear the full cost of incorrect language detection, while sighted users are unaffected — but it represents a clear WCAG Level A failure.

## Remediation

Set the `lang` attribute on the root `<html>` element with a valid BCP 47 language code:

```html
<html lang="en">
```

In Next.js App Router, set it in `app/layout.tsx`:

```tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}
```

For multi-language sites, set `lang` dynamically based on the current locale: `lang={params.locale}`. Common codes: `en` (English), `es` (Spanish), `fr` (French), `de` (German), `pt` (Portuguese), `ja` (Japanese), `zh` (Chinese).

## Detection

- **ID:** `html-lang`
- **Severity:** `medium`
- **What to look for:** Extract the `<html>` opening tag from the HTML document. Count all `lang` attributes present in the document (on `<html>` and any child elements). Check for the presence of a `lang` attribute on `<html>`. If present, extract its value and verify it matches a valid BCP 47 language tag format (2-3 letter language code, optionally followed by a region code, e.g., `en`, `en-US`, `fr`, `zh-Hans`). The value must be at least 2 characters long.
- **Pass criteria:** The `<html>` tag has a `lang` attribute with a non-empty value that is at least 2 characters long and follows the BCP 47 language tag format (e.g., `en`, `en-US`, `fr`). Report the actual language code found.
- **Fail criteria:** No `lang` attribute on `<html>`, or the value is empty, or the value is a single character or obviously invalid (e.g., `lang="x"`).
- **Skip (N/A) when:** The response `Content-Type` is not HTML (e.g., JSON API, XML).
- **Detail on fail:** `"<html> tag has no lang attribute — screen readers cannot determine the page language"`
- **Remediation:** The `lang` attribute on `<html>` tells screen readers which language to use for pronunciation. Without it, screen readers guess (often incorrectly). Set it on your root HTML element:

  ```html
  <html lang="en">
  ```

  In Next.js App Router, set it in `app/layout.tsx`: `<html lang="en">`. For multi-language sites, set it dynamically based on the locale. Valid codes: `en` (English), `es` (Spanish), `fr` (French), `de` (German), `ja` (Japanese), `zh` (Chinese).

## External references

- wcag 3.1.1
- section-508 504.2

Taxons: accessibility

HTML version: https://auditbuffet.com/patterns/ab-002527
