/ ← Meta Tag Fixes / lang Attribute
In this guide
  1. What the lang attribute actually does
  2. What lang does and does not do for search
  3. Choosing a valid value
  4. Finding the problem
  5. The fix, step by step
  6. Where to set it on common platforms
  7. Edge cases and things that trip people up
  8. Keeping it right
  9. Questions and answers

What the lang attribute actually does

The attribute sits on the root element of the document and applies to everything inside it unless a child element sets its own value:

<!DOCTYPE html>
<html lang="en-GB">
<head>
  <meta charset="utf-8">
  <title>Boiler servicing in Chesterfield | Northgate Heating</title>
</head>

That one value is read by several different pieces of software, and each does something different with it:

ReaderWhat it does with langWhat goes wrong without it
Screen readers such as NVDA, JAWS and VoiceOverPick the speech voice and pronunciation rules for the language, where the voice is installedThe reader falls back to the user's default voice, so a French page may be read aloud with English sounds
BrowsersChoose a spelling dictionary for form fields, and inform the offer to translate the pageSpell checks underline correct British spellings; translation offers appear at the wrong time or not at all
CSShyphens: auto needs a language to know where words may break; the :lang() selector matches on itAutomatic hyphenation silently does nothing
Quotation marksThe <q> element uses the quotation style of the languageGerman or French text gets English quote marks
Accessibility checkersTest WCAG 2.2 success criterion 3.1.1, Language of Page, at Level AAn automatic failure in audits and accessibility statements

WCAG 2.2 has a second, related criterion: 3.1.2 Language of Parts, at Level AA. It asks that a passage in a different language from the rest of the page is marked with its own lang, so assistive technology can switch voice for that passage and switch back afterwards.

Choosing a valid value

The value is a language tag in the format defined by BCP 47, the internet standard for language identifiers. For almost every site it is either a two-letter language code on its own, or a language code followed by a hyphen and a two-letter region code.

ValueValid?When to use it
enYesEnglish with no particular region intended
en-GBYesBritish English: the right choice for most UK businesses writing colour, organise and centre
en-USYesAmerican English. Wrong for a UK site, and usually present only because a theme shipped with it
en-UKNoUK is not the registered region subtag for the United Kingdom; GB is
en_GBNoUnderscores belong to og:locale and some software locales, not to HTML
english or EN-GB-LondonNoLanguage names and invented subtags are not recognised
cy or cy-GBYesWelsh
gdYesScottish Gaelic
zh-Hans / zh-HantYesChinese in simplified or traditional script, where script matters more than region
Empty: lang=""Valid but unhelpfulMeans the language is unknown; checkers treat it as missing

Tags are case-insensitive, but the usual convention is a lower-case language and an upper-case region: en-GB. Do not add a region you do not mean. If a page is written for English speakers anywhere, plain en is more honest than picking a country.

Sites that serve more than one language

Each language version needs its own value on its own pages. The French pages of a bilingual site should say lang="fr" (or fr-FR, fr-BE and so on), not inherit the English value from a shared layout. The most common fault on multilingual sites is a single hard-coded value in the master template, which makes every translation claim to be English.

Finding the problem

Start with the raw HTML the server sends, because a script can change the attribute after the page loads and browser tools show only the final state.

curl -s https://example.co.uk/ | grep -io "<html[^>]*>"

Then compare it with what the browser ends up with. In the developer tools console, type:

document.documentElement.lang

If the first shows nothing and the second shows a value, a script is setting it. That is better than nothing for screen reader users, but anything that reads the HTML without running scripts, including many validators, sees no language. Move the value into the server-rendered markup.

What checkers report

Test more than the home page. Blog posts, product pages, landing pages built in a page builder and checkout pages are often served by different templates, and each can have its own html tag.

The fix, step by step

Step 1

Read the lang value the server sends

Run one page of each template through the Meta Tag Analyzer, then fetch the same addresses with curl and look at the opening <html> tag. Write down what you find for each page type: missing, empty, en-US, an invalid value such as en-UK, or a correct value. Also note whether a script changes it afterwards, by comparing with document.documentElement.lang in the browser console.

Step 2

Choose a valid language tag

Pick the value that matches how the text is actually written. For a UK business writing British English, use en-GB; for English written for no particular country, use en. For other languages use the two-letter code, adding a region only when the content is genuinely regional. Never use en-UK, underscores or language names, because none of them are valid tags, and checkers will keep failing the page until they are replaced.

Step 3

Set lang once in the layout

Put the attribute on the <html> element in the one file that every page shares: header.php through language_attributes() in WordPress, theme.liquid in Shopify, the root layout in Next.js, or the base template of a static site generator. Take the value from the site or page language setting rather than typing it, so translated pages get their own value automatically and nobody has to remember to change it later.

Step 4

Mark passages in other languages

Where a page contains a quotation, a product name or a paragraph in another language, wrap that passage in an element carrying its own attribute, such as <span lang="fr"> or <blockquote lang="cy">. Screen readers then switch voice for that passage. Leave out common borrowed words and proper names that English readers pronounce in the English way, because marking those makes speech sound stranger, not better.

Step 5

Add dir for right-to-left scripts

If any page or passage is in Arabic, Hebrew, Persian or Urdu, add dir="rtl" next to the language, for example <html lang="ar" dir="rtl">. The lang attribute does not set text direction on its own. For user-supplied text whose direction you cannot predict, such as names in reviews, use dir="auto" or the <bdi> element so it does not scramble the punctuation of the surrounding English.

Step 6

Retest with an accessibility checker

Clear any page cache, then run Lighthouse or axe on one page of each template and confirm the language audits pass. Run the Meta Tag Analyzer again on the same pages to check the value now matches og:locale and any hreflang entries. Finally, open a page with a screen reader such as NVDA or VoiceOver and listen to a marked passage to confirm the voice changes and changes back.

Where to set it on common platforms

WordPress

Well-built themes print the attribute through the language_attributes() function in header.php, which reads the Site Language chosen under Settings, General. Choosing English (UK) there produces lang="en-GB".

<html <?php language_attributes(); ?>>

If changing the Site Language makes no difference, the theme has hard-coded the value. Edit it in a child theme rather than the parent, so a theme update does not undo the change. Multilingual plugins such as WPML and Polylang switch the value for each language through the same function, which is another reason not to hard-code it.

Shopify

Current Shopify themes set the value from the storefront's active language in layout/theme.liquid:

<html class="no-js" lang="{{ request.locale.iso_code }}">

If yours shows a fixed value, replace it with the Liquid variable, and check any alternative layout files such as a separate checkout or password layout. The published default language is set under Settings, Languages.

Next.js and other JavaScript frameworks

In the App Router the html element is written in the root app/layout.tsx, so the attribute goes there directly. Sites with several languages usually put the locale in a route segment and read it in that layout. In the Pages Router it belongs in pages/_document on the <Html> component, or is set for you by the built-in i18n routing. Avoid setting it with client-side code, because the first HTML the server sends will then have none.

export default function RootLayout({ children }) {
  return (
    <html lang="en-GB">
      <body>{children}</body>
    </html>
  );
}

Static sites and hand-built pages

Every file has its own html tag, so a search across the project is the quickest check. Most static site generators, such as Hugo, Eleventy and Jekyll, keep it in one base layout and read a language value from the site configuration.

Edge cases and things that trip people up

⚠️ Do not mark a page with a language it is not written in, hoping to rank in another country. It does not work for Google, which reads the visible text, and it makes the page harder to use for anyone relying on a screen reader.

Keeping it right

For the rest of the head, the Meta Analyzer Guide explains each check the analyzer runs, and the Accessibility Guide covers the wider WCAG picture that lang is one small part of.

Questions and answers

1. Does the lang attribute help my Google rankings?

Not directly. Google's documentation says it identifies the language of a page mainly from its visible text and does not rely on code-level signals such as the lang attribute. So a missing value will not stop an English page appearing for English searches, and a wrong value will not move it into another country. The attribute is still worth fixing because it is an accessibility requirement, it changes how browsers and screen readers handle the page, and other tools may use it as a signal.

2. Should a UK website use en-GB or en?

Use en-GB if the text is written in British English for a British audience, which is true of most UK business sites. Use plain en if you write for English speakers in general and have no particular country in mind. Both are valid and both pass accessibility checks. The practical difference is small: en-GB lets browsers pick a British spelling dictionary and lets screen readers that have a British voice installed use it, which suits spellings like colour and organise.

3. Is en-UK a valid lang value?

No. Language tags use the region codes from the international country code list, and the code for the United Kingdom there is GB, not UK. Validators and accessibility checkers will report en-UK as an invalid value, and software that reads the attribute may ignore it. The same mistake appears in og:locale as en_UK and in hreflang as en-uk. Change all of them to the GB form, written with a hyphen in HTML and hreflang, and with an underscore in og:locale.

4. Why does WordPress still say en-US after I changed the site language?

Because the theme is not using the language_attributes function and has typed the value directly into header.php, or a page builder or caching layer is serving an old copy. Clear any page and CDN cache first, then view the source. If the value is still en-US, open the theme's header file and replace the fixed value with a call to language_attributes, in a child theme so an update does not overwrite it. Some page builders have their own canvas template that needs the same change.

5. Do I need to mark every foreign word with its own lang?

No. The WCAG criterion on language of parts excludes proper names, technical terms, words of an unknown language, and words that have become part of the surrounding language, such as café, déjà vu or croissant in English. Mark whole phrases, sentences, quotations and passages where a listener would otherwise hear the text mispronounced so badly it is hard to follow. Marking single borrowed words usually makes speech sound more awkward, because the voice changes mid-sentence.

6. What is the difference between lang and hreflang?

The lang attribute describes the language of the document you are reading, for browsers, screen readers and other software that processes that page. Hreflang annotations are a list of links telling search engines where to find the equivalent page in other languages or for other regions, so they can show the right version to each searcher. A single-language site needs a lang attribute but no hreflang at all. A multilingual site needs both, and each translated page should carry its own lang value.

7. Can I set the lang attribute with JavaScript?

You can, and screen readers running in a browser will usually respect a value set by script. But anything that reads the raw HTML without running scripts, including many validators, crawlers and audit tools, will see a page with no language. It also adds a moment where the page exists without one. Put the value in the HTML the server sends, generated from your site or page language setting, and only change it with script if the page genuinely switches language without reloading.

Check the lang value with the rest of your head

The Meta Tag Analyzer reads the head of your page and checks the title, description, canonical, robots directives, viewport, lang, Open Graph and X card tags, then lists each finding with the guide that fixes it.

Open Meta Tag Fixes →
💬 Got a problem?
Related Guides: All Meta Tag Fixes  ·  Fixing Hreflang Language Codes  ·  Fixing og:locale Issues  ·  Meta Analyzer Guide  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.