View contents
Complete Technical Guide to Language Declaration: BCP 47, WCAG, and International SEO
Introduction
If you’re already familiar with language declaration fundamentals from our introductory guide, this advanced technical guide will equip you with deep knowledge of BCP 47, complete WCAG compliance, and implementation strategies for complex multilingual sites.
Correct language declaration isn’t just an HTML tag—it’s the foundation of international accessibility, effective multilingual SEO, and user experience for global audiences.
BCP 47 Anatomy: The Standard Behind lang
What is BCP 47?
BCP 47 (Best Current Practice 47) is the IETF standard that defines the structure of language tags¹. It’s the format used by HTML’s lang attribute and is much more than two-letter codes.
Complete Structure of a BCP 47 Tag
language-extlang-script-region-variant-extension-privateuse
| Component | Example | Description |
|---|---|---|
| language | en |
ISO 639-1 code (required) |
| extlang | cmn (Mandarin) |
Sub-language (rare) |
| script | Latn, Hans |
Writing system |
| region | US, GB, 419 |
Country or region |
| variant | valencia |
Dialect variant |
| extension | u-nu-thai |
Unicode extensions |
| privateuse | x-custom |
Private use |
Practical BCP 47 Examples
<!-- Generic English -->
<html lang="en">
<!-- English (United States) -->
<html lang="en-US">
<!-- English (United Kingdom) -->
<html lang="en-GB">
<!-- English (Australia) -->
<html lang="en-AU">
<!-- Simplified Chinese (Mainland China) -->
<html lang="zh-Hans-CN">
<!-- Traditional Chinese (Taiwan) -->
<html lang="zh-Hant-TW">
<!-- Brazilian Portuguese -->
<html lang="pt-BR">
<!-- Serbian in Cyrillic script -->
<html lang="sr-Cyrl">
<!-- Serbian in Latin script -->
<html lang="sr-Latn">
<!-- Azerbaijani in Arabic script -->
<html lang="az-Arab">
<!-- Spanish (Latin America - region code 419) -->
<html lang="es-419">
<!-- English with Unicode extension for Thai numerals -->
<html lang="en-u-nu-thai">
When to Use Each Specificity Level
Language Only (en, es, fr)
Use when:
- Content is understandable to all speakers of the language
- No significant regional differences
- You want maximum compatibility
<!-- Technical article about programming - universal -->
<html lang="en">
Language + Region (en-US, en-GB, pt-BR)
Use when:
- Content has region-specific vocabulary
- Important spelling differences (color vs colour)
- Geographic targeting for SEO
- Country-specific legal or regulatory content
<!-- Online store with USD prices -->
<html lang="en-US">
<!-- Legal documentation for UK -->
<html lang="en-GB">
Language + Script (zh-Hans, sr-Cyrl)
Use when:
- The language uses multiple writing systems
- You want to specify the script without binding to a region
<!-- Simplified Chinese (without specifying country) -->
<html lang="zh-Hans">
WCAG 2.2 Compliance: Complete Requirements
Criterion 3.1.1: Language of Page (Level A)²
Requirement: The default human language of each Web page can be programmatically determined.
Sufficient techniques:
<!-- H57: Using the lang attribute on the html element -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Website</title>
</head>
<body>
<!-- All content in English -->
</body>
</html>
Common errors causing non-compliance:
- Missing lang attribute entirely:
<!-- ❌ FAILS WCAG 3.1.1 -->
<html>
- Invalid language code:
<!-- ❌ FAILS WCAG 3.1.1 - "english" is not a valid code -->
<html lang="english">
- Wrong language for content:
<!-- ❌ FAILS WCAG 3.1.1 - Spanish content, declared as English -->
<html lang="en">
<body>
<h1>Bienvenido a nuestro sitio</h1>
</body>
</html>
Criterion 3.1.2: Language of Parts (Level AA)³
Requirement: The human language of each passage or phrase in the content can be programmatically determined except for proper names, technical terms, words of indeterminate language, and words or phrases that have become part of the vernacular of the immediately surrounding text.
Sufficient techniques:
<html lang="en">
<body>
<p>This article is about web development.</p>
<!-- Spanish quote - REQUIRES lang -->
<blockquote lang="es">
<p>"El mejor código es el que no existe."</p>
<cite>— Anonymous Spanish Developer</cite>
</blockquote>
<p>As the quote above states, simplicity is key.</p>
<!-- Technical term in code - DOES NOT require lang (technical term) -->
<p>We use <code>localStorage</code> for data storage.</p>
<!-- Proper noun - DOES NOT require lang -->
<p>The company Google was founded in 1998.</p>
<!-- Foreign word adopted into English - DOES NOT require lang -->
<p>The software has a user-friendly interface.</p>
</body>
</html>
When to declare language on sections:
| Content | Requires lang? | Reason |
|---|---|---|
| Textual quotes | ✅ Yes | Significant content in another language |
| Poems/lyrics | ✅ Yes | Creative content in original language |
| Testimonials | ✅ Yes | User’s voice in their language |
| Source code | ⚠️ Optional | Generally lang="en" |
| Technical terms | ❌ No | Explicit WCAG exception |
| Proper nouns | ❌ No | Explicit WCAG exception |
| Adopted loanwords | ❌ No | Part of local vernacular |
Impact on Assistive Technologies
Screen readers and language declaration:
<!-- Without lang: NVDA/JAWS pronounces "Bonjour" with English phonetics -->
<html>
<body><h1>Bonjour</h1></body>
</html>
<!-- With lang="fr": Correct French pronunciation -->
<html lang="fr">
<body><h1>Bonjour</h1></body>
</html>
Popular screen reader behavior:
| Reader | Without lang | With wrong lang | With correct lang |
|---|---|---|---|
| NVDA | Uses system language | Incorrect pronunciation | ✅ Correct |
| JAWS | Uses default language | Wrong voice change | ✅ Correct |
| VoiceOver | Automatic inference | May change voice | ✅ Correct |
| TalkBack | Uses device language | Forced pronunciation | ✅ Correct |
International SEO: hreflang and Language Declaration
Relationship Between lang and hreflang
The lang attribute and hreflang tags work together but have different purposes⁴:
| Attribute | Purpose | Audience |
|---|---|---|
lang |
Declare content language | Browsers, screen readers |
hreflang |
Indicate alternate versions | Search engines |
Correct implementation:
<!-- English version -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Website</title>
<link rel="canonical" href="https://example.com/en/">
<!-- hreflang for international SEO -->
<link rel="alternate" hreflang="en" href="https://example.com/en/">
<link rel="alternate" hreflang="es" href="https://example.com/es/">
<link rel="alternate" hreflang="pt-BR" href="https://example.com/pt-br/">
<link rel="alternate" hreflang="x-default" href="https://example.com/en/">
</head>
<body>
<h1>Welcome</h1>
</body>
</html>
Strategies for Multilingual Sites
URL Structure
# By subdirectory (recommended)
example.com/en/ → lang="en"
example.com/es/ → lang="es"
example.com/pt-br/ → lang="pt-BR"
# By subdomain
en.example.com/ → lang="en"
es.example.com/ → lang="es"
# By country domain
example.com/ → lang="en"
example.es/ → lang="es"
example.com.br/ → lang="pt-BR"
Implementation in Modern Frameworks
Vue 3 with Vue Router:
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/:lang(en|es|pt-br)',
children: [
{ path: '', component: Home },
{ path: 'about', component: About }
]
}
]
// composables/useLanguage.ts
import { useHead } from '@vueuse/head'
import { useRoute } from 'vue-router'
import { computed } from 'vue'
export function useLanguage() {
const route = useRoute()
const currentLang = computed(() => {
const lang = route.params.lang as string
const langMap: Record<string, string> = {
'en': 'en',
'es': 'es',
'pt-br': 'pt-BR'
}
return langMap[lang] || 'en'
})
useHead({
htmlAttrs: {
lang: currentLang
}
})
return { currentLang }
}
Next.js with i18n:
// next.config.js
module.exports = {
i18n: {
locales: ['en', 'es', 'pt-BR'],
defaultLocale: 'en',
localeDetection: true
}
}
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html> {/* Next.js injects lang automatically */}
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
Nuxt 3 with @nuxtjs/i18n:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
locales: [
{ code: 'en', iso: 'en-US', name: 'English' },
{ code: 'es', iso: 'es-ES', name: 'Español' },
{ code: 'pt-br', iso: 'pt-BR', name: 'Português' }
],
defaultLocale: 'en',
strategy: 'prefix'
}
})
// The module handles lang automatically
Content-Language vs lang: Critical Differences
HTTP Header Content-Language
HTTP/1.1 200 OK
Content-Language: en
Content-Type: text/html; charset=UTF-8
HTML lang Attribute
<html lang="en">
Detailed Comparison
| Aspect | Content-Language HTTP | HTML lang |
|---|---|---|
| Purpose | Target audience of resource | Content language |
| Reading | Before parsing HTML | When parsing HTML |
| Accessibility | ❌ Not used | ✅ Used by screen readers |
| SEO | Weak signal | Stronger signal |
| Granularity | Document level only | Element by element |
| Recommendation | Optional | Required (WCAG Level A) |
Recommendation: Always use lang in HTML. The Content-Language header is optional and less useful.
Special Cases and Solutions
Mixed Content
<html lang="en">
<body>
<article>
<h1>Review: "Cien años de soledad"</h1>
<p>This classic novel by Gabriel García Márquez is a masterpiece.</p>
<!-- Quote from the book in Spanish -->
<blockquote lang="es">
<p>"Muchos años después, frente al pelotón de fusilamiento, el coronel Aureliano Buendía había de recordar aquella tarde remota en que su padre lo llevó a conocer el hielo."</p>
</blockquote>
<p>As we see, Márquez opens with one of literature's most famous sentences.</p>
</article>
</body>
</html>
RTL (Right-to-Left) Languages
<!-- Arabic -->
<html lang="ar" dir="rtl">
<!-- Hebrew -->
<html lang="he" dir="rtl">
<!-- Persian/Farsi -->
<html lang="fa" dir="rtl">
RTL sections in LTR document:
<html lang="en">
<body>
<p>This article discusses Middle Eastern cuisine.</p>
<blockquote lang="ar" dir="rtl">
<p>الطعام العربي لذيذ جدا</p>
</blockquote>
</body>
</html>
Languages Without ISO 639-1 Codes
Some languages only have ISO 639-2 (3-letter) or ISO 639-3 codes:
<!-- Nahuatl (Aztec) - Only ISO 639-2/3 -->
<html lang="nah">
<!-- Mapudungun (Mapuche) - Only ISO 639-3 -->
<span lang="arn">Mari mari</span>
<!-- Sign languages -->
<video lang="ase"> <!-- American Sign Language -->
Verification and Testing
Validation Tools
- W3C Validator: Verifies HTML syntax including
lang - axe DevTools: WCAG accessibility audit
- WAVE: Detects language declaration errors
- UXR SEO Analyzer: Specific lang and SEO verification
Verification Checklist
Level A (Required)
- [ ]
<html lang="xx">present on all pages - [ ] Valid language code per BCP 47
- [ ] Declared language matches main content
Level AA (Recommended)
- [ ] Sections in other languages have specific
lang - [ ] Textual quotes have declared language
- [ ] Significant language changes marked
International SEO
- [ ] hreflang implemented for all versions
- [ ] x-default defined for fallback
- [ ] Consistency between lang and hreflang
- [ ] Canonical URLs per language
How to Verify with UXR SEO Analyzer
Verify your language configuration with our extension:
- Install the extension UXR SEO Analyzer
- Navigate to your website
- Open the extension → “Basic SEO” tab
- Check “Language Declaration”
The extension detects:
- ✅ Presence of lang attribute
- ✅ BCP 47 code validity
- ⚠️ Inconsistencies between declared language and content
- ⚠️ Sections without language declaration
- ❌ Invalid or malformed codes
Next Steps
Continue improving your multilingual implementation:
Related articles:
- Language Declaration: Fundamentals
- Hreflang: Complete Implementation
- Meta Robots: Indexing Control
- International SEO: Advanced Strategies
References
This article was created using official authoritative sources:
[1] W3C: Language tags in HTML and XML https://www.w3.org/International/articles/language-tags/ Complete W3C specification on BCP 47 language tags, including structure, syntax, and use cases. Authoritative reference for correct language code construction.
[2] WCAG 2.2: Success Criterion 3.1.1 Language of Page https://www.w3.org/WAI/WCAG22/Understanding/language-of-page.html WCAG Level A conformance criterion requiring programmatic language declaration for pages. Includes sufficient techniques and common failures.
[3] WCAG 2.2: Success Criterion 3.1.2 Language of Parts https://www.w3.org/WAI/WCAG22/Understanding/language-of-parts.html WCAG Level AA conformance criterion for language declaration in specific sections. Defines exceptions for technical terms and proper nouns.
[4] Google Search Central: Tell Google about localized versions https://developers.google.com/search/docs/specialty/international/localized-versions Official Google documentation on hreflang implementation and language signals for international SEO.
[5] IANA Language Subtag Registry https://www.iana.org/assignments/language-subtag-registry/ Official IANA registry with all valid language, region, script, and variant codes for use in BCP 47 tags.
Source coverage: HIGH - W3C, WCAG, Google Search Central, and IANA sources provide complete authoritative coverage.
Additional Resources
Note: This article is part of our advanced technical SEO and internationalization series. Explore all articles in the Basic SEO Hub.
Author: UXR Chile Team Last updated: December 2025 Reading time: 14 minutes