i18n
Internationalization (i18n) Skill
This skill ensures HTML pages are properly structured for internationalization and localization.
Essential Attributes
The lang Attribute (REQUIRED)
Every HTML document MUST have a language declaration:
<html lang="en">
Use BCP 47 language tags:
| Tag | Language |
|---|---|
en |
English |
en-US |
American English |
en-GB |
British English |
es |
Spanish |
fr |
French |
de |
German |
zh |
Chinese |
zh-Hans |
Simplified Chinese |
zh-Hant |
Traditional Chinese |
ja |
Japanese |
ko |
Korean |
ar |
Arabic |
he |
Hebrew |
ru |
Russian |
pt |
Portuguese |
pt-BR |
Brazilian Portuguese |
Inline Language Changes
Mark content in different languages:
<p>The French phrase <span lang="fr">c'est la vie</span> means "that's life".</p>
<blockquote lang="de">
<p>Die Grenzen meiner Sprache bedeuten die Grenzen meiner Welt.</p>
<footer>— Ludwig Wittgenstein</footer>
</blockquote>
The dir Attribute (RTL Languages)
For right-to-left languages (Arabic, Hebrew, Persian, Urdu):
<html lang="ar" dir="rtl">
For mixed content:
<p dir="rtl" lang="ar">مرحبا بالعالم</p>
<p dir="ltr" lang="en">Hello World</p>
Use dir="auto" for user-generated content:
<input type="text" dir="auto" name="comment"/>
<textarea dir="auto"></textarea>
Language Alternatives
The hreflang Attribute
Link to alternate language versions:
<head>
<!-- Self-referential -->
<link rel="alternate" hreflang="en" href="https://example.com/page"/>
<!-- Other languages -->
<link rel="alternate" hreflang="es" href="https://example.com/es/page"/>
<link rel="alternate" hreflang="fr" href="https://example.com/fr/page"/>
<link rel="alternate" hreflang="de" href="https://example.com/de/page"/>
<!-- Default/fallback -->
<link rel="alternate" hreflang="x-default" href="https://example.com/page"/>
</head>
Language Switcher Pattern
<nav aria-label="Language selection">
<ul>
<li><a href="/en/" hreflang="en" lang="en">English</a></li>
<li><a href="/es/" hreflang="es" lang="es">Español</a></li>
<li><a href="/fr/" hreflang="fr" lang="fr">Français</a></li>
<li><a href="/ar/" hreflang="ar" lang="ar" dir="rtl">العربية</a></li>
</ul>
</nav>
Character Encoding
UTF-8 (REQUIRED)
Always declare UTF-8 encoding as the first element in <head>:
<head>
<meta charset="utf-8"/>
<!-- Other meta tags after -->
</head>
Special Characters
Use actual Unicode characters, not HTML entities when possible:
<!-- Prefer actual characters -->
<p>Price: €50 • Copyright © 2024 • Température: 20°C</p>
<!-- Entities only when needed for markup -->
<p><tag> shows a tag</p>
Translation-Friendly Markup
Avoid Concatenation
Do not build sentences from fragments:
<!-- BAD: Fragments break translation -->
<p><span>You have</span> <span class="count">5</span> <span>items</span></p>
<!-- GOOD: Complete translatable unit -->
<p>You have <data value="5">5 items</data> in your cart.</p>
Use <data> for Values
Separate translatable text from raw values:
<p>Price: <data value="49.99">$49.99</data></p>
<p>Status: <data value="active">Active</data></p>
Avoid Text in Images
Text in images cannot be translated:
<!-- BAD -->
<img src="welcome-banner.jpg" alt="Welcome to our site"/>
<!-- GOOD -->
<figure>
<img src="banner-background.jpg" alt=""/>
<figcaption>Welcome to our site</figcaption>
</figure>
Use translate Attribute
Mark content that should not be translated:
<!-- Brand names, code, proper nouns -->
<p>Download <span translate="no">Acme Pro</span> today.</p>
<code translate="no">npm install my-package</code>
<p>Contact: <span translate="no">support@example.com</span></p>
Date, Time, and Numbers
Semantic Time Element
Always use <time> with machine-readable datetime:
<!-- Dates -->
<time datetime="2024-12-25">December 25, 2024</time>
<time datetime="2024-12-25">25/12/2024</time>
<time datetime="2024-12-25">25 décembre 2024</time>
<!-- Times -->
<time datetime="14:30">2:30 PM</time>
<time datetime="14:30">14:30</time>
<time datetime="14:30">14h30</time>
<!-- Full datetime -->
<time datetime="2024-12-25T14:30:00Z">December 25, 2024 at 2:30 PM UTC</time>
<!-- Durations -->
<time datetime="PT2H30M">2 hours and 30 minutes</time>
Numbers and Currency
Use <data> to preserve raw values:
<!-- Currency -->
<data value="USD 99.99">$99.99</data>
<data value="EUR 99.99">99,99 €</data>
<data value="JPY 10000">¥10,000</data>
<!-- Numbers -->
<data value="1000000">1,000,000</data>
<data value="1000000">1 000 000</data>
<data value="1000000">1.000.000</data>
Pluralization
Structure for Translation Systems
Avoid English-specific plural logic:
<!-- BAD: Assumes English plural rules -->
<p>You have <span class="count">1</span> item(s)</p>
<!-- GOOD: Complete phrases for each case -->
<p data-plural-zero="You have no items"
data-plural-one="You have 1 item"
data-plural-other="You have {count} items">
You have 5 items
</p>
CLDR Plural Categories
Different languages have different plural rules:
| Category | English | Russian | Arabic |
|---|---|---|---|
| zero | - | - | 0 items |
| one | 1 item | 1, 21, 31... | 1 item |
| two | - | - | 2 items |
| few | - | 2-4, 22-24... | 3-10 items |
| many | - | 5-20, 25-30... | 11-99 items |
| other | 2+ items | - | 100+ items |
Accessibility for i18n
Language Changes for Screen Readers
Screen readers switch pronunciation based on lang:
<p>The German word <span lang="de">Weltanschauung</span> has no English equivalent.</p>
Reading Direction
Ensure logical reading order in RTL:
<article dir="rtl" lang="ar">
<h1>عنوان المقال</h1>
<p>نص الفقرة هنا.</p>
<!-- LTR content within RTL -->
<pre dir="ltr"><code>console.log("Hello");</code></pre>
</article>
Content Structure for Translation
Meaningful IDs
Use semantic IDs that survive translation:
<!-- BAD -->
<section id="section-1">
<h2 id="welcome-message">Welcome!</h2>
<!-- GOOD -->
<section id="introduction">
<h2 id="hero-heading">Welcome!</h2>
Consistent Structure
Maintain parallel structure across languages:
<!-- All language versions should have same structure -->
<article>
<header>
<h1><!-- Translated title --></h1>
<p class="byline"><!-- Translated byline --></p>
</header>
<div class="content">
<!-- Translated content -->
</div>
<footer>
<!-- Translated footer -->
</footer>
</article>
Meta Tags for i18n
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!-- Language/locale -->
<meta http-equiv="content-language" content="en"/>
<meta property="og:locale" content="en_US"/>
<meta property="og:locale:alternate" content="es_ES"/>
<meta property="og:locale:alternate" content="fr_FR"/>
<!-- hreflang links -->
<link rel="alternate" hreflang="en" href="https://example.com/"/>
<link rel="alternate" hreflang="es" href="https://example.com/es/"/>
<link rel="alternate" hreflang="x-default" href="https://example.com/"/>
</head>
i18n Checklist
Before finalizing internationalized content:
-
<html lang="...">attribute set correctly -
<meta charset="utf-8"/>is first in<head> -
dir="rtl"set for RTL languages -
hreflanglinks for all language versions - Inline
langattributes for foreign phrases -
<time datetime="...">for all dates/times -
<data value="...">for numbers and currency -
translate="no"on brand names and code - No text concatenation that breaks translation
- No text embedded in images
- Consistent structure across language versions
Common Mistakes
| Mistake | Problem | Solution |
|---|---|---|
Missing lang |
Screen readers use wrong pronunciation | Always set <html lang="..."> |
Missing dir |
RTL text displays incorrectly | Add dir="rtl" for Arabic, Hebrew, etc. |
| Hardcoded dates | "12/25/2024" means different things | Use <time datetime="..."> |
| Text in images | Cannot be translated | Use HTML text with CSS styling |
| Concatenation | Word order varies by language | Use complete translatable phrases |
| Entity overuse | Harder to read/edit | Use actual Unicode characters |
Related Skills
- xhtml-author - Write valid XHTML-strict HTML5 markup
- javascript-author - Write vanilla JavaScript for Web Components with function...
- accessibility-checker - Ensure WCAG2AA accessibility compliance
- metadata - HTML metadata and head content
More from profpowell/vanilla-breeze
api-client
Fetch API patterns with error handling, retry logic, and caching. Use when building API integrations, handling network failures, or implementing offline-first data fetching.
44validation
Validate data with JSON Schema and AJV. Use when validating API requests, form submissions, database inputs, or any data boundaries. Provides deterministic validation with consistent error formats.
43fake-content
Generate realistic fake content for HTML prototypes. Use when populating pages with sample text, products, testimonials, or other content. NOT generic lorem ipsum.
15xhtml-author
Write valid XHTML-strict HTML5 markup. Use when creating HTML files, editing markup, building web pages, or writing any HTML content. Ensures semantic structure and XHTML syntax.
10layout-grid
Design-focused grid layout system with fluid scaling, responsive columns, and resolution-independent patterns. Use when creating page layouts, card grids, or multi-column designs.
8service-worker
Service worker patterns for offline support, caching strategies, and PWA functionality. Use when implementing offline-first features, caching, or background sync.
8