references/locale-checklist.md
# Locale Checklist
A per-locale checklist of everything that needs to adapt beyond translation. Walk through this for each locale before launch, and revisit when adding new content.
---
## URL and structure
- [ ] Locale URL pattern chosen and consistent (subfolder, subdomain, or ccTLD)
- [ ] Locale code uses standard format (BCP 47: `en`, `en-US`, `de-DE`, `zh-Hant`)
- [ ] Default locale handling decided (apex vs folder)
- [ ] URL slugs translated where appropriate (e.g., `/products/` → `/produkte/` for German)
- [ ] Or URL slugs kept consistent across locales (acceptable for many sites; prioritizes consistency over native readability)
---
## Search engine signals
- [ ] hreflang tags present on every page, every locale
- [ ] hreflang reciprocity verified (page A links to B, B links to A)
- [ ] hreflang includes `x-default` pointing to the fallback
- [ ] Canonical tags self-reference (each locale page canonicals to itself)
- [ ] Sitemaps include all locales (one sitemap per locale or a combined sitemap)
- [ ] robots.txt allows all locale paths
- [ ] Schema.org `inLanguage` attribute on appropriate types
---
## Translation completeness
- [ ] Page content translated
- [ ] Page titles and meta descriptions translated
- [ ] Image alt text translated
- [ ] Form labels translated
- [ ] Form validation messages translated
- [ ] Error pages (404, 500) translated
- [ ] Success messages translated
- [ ] Email templates translated (transactional, marketing)
- [ ] PDF or downloadable assets translated (or alternate version provided)
- [ ] Help and FAQ content translated
- [ ] Legal pages translated (privacy, terms, cookies)
---
## Currency and money
- [ ] Currency displayed matches the locale (EUR for euro zone, GBP for UK, JPY for Japan, etc.)
- [ ] Currency symbol position correct ($1,000 vs 1.000 €)
- [ ] Decimal separator correct (1,000.50 vs 1.000,50 vs 1 000,50)
- [ ] Thousand separator correct (comma, period, space, or none)
- [ ] Pricing tables localized to native pricing (not direct conversion)
- [ ] Tax handling (inclusive vs exclusive) matches local convention
---
## Numbers and units
- [ ] Number format follows locale (1,234.56 vs 1.234,56)
- [ ] Negative numbers (-5 vs (5)) follow convention
- [ ] Percentages format correctly (5% vs 5 %)
- [ ] Measurement units match (km vs miles, kg vs lb, °C vs °F)
- [ ] Paper sizes if relevant (A4 vs Letter)
---
## Dates and times
- [ ] Date format matches (DD/MM/YYYY for most of Europe, MM/DD/YYYY for US, YYYY-MM-DD ISO)
- [ ] Day-of-week localization (Monday vs Lundi vs 月曜日)
- [ ] Month names localized
- [ ] First day of week (Monday in Europe, Sunday in US)
- [ ] Time format (12-hour with AM/PM vs 24-hour)
- [ ] Time zone display where relevant
- [ ] Relative time strings localized ("2 hours ago" → "il y a 2 heures")
---
## Names and addresses
- [ ] Name field structure matches (single name field for some cultures, given/family for others, family-first ordering for some Asian languages)
- [ ] Address form fields adapt to country
- US: street, city, state, ZIP
- UK: street, town, county, postcode
- Germany: street, postal code, city
- Japan: postal code, prefecture, city, ward, block, building
- [ ] Postal code validation per country
- [ ] State/region/prefecture/county field renamed appropriately
- [ ] Country dropdown ordered by region or alphabetical (avoid US-first if not US-centric audience)
---
## Phone numbers
- [ ] Country code defaulted appropriately
- [ ] E.164 format stored (+CCNNNNNNNNNN)
- [ ] Display format adapts to country
- [ ] Validation accepts international formats
---
## Imagery and media
- [ ] Images depict locally relevant people, places, products
- [ ] Avoided imagery that's offensive in the locale (gestures, symbols, color associations)
- [ ] Cultural references in screenshots/examples are appropriate
- [ ] Image text translated (text in images doesn't auto-translate)
- [ ] Video subtitles or dubbing in the locale language
---
## Layout and direction
- [ ] LTR/RTL handling correct for the script
- [ ] CSS logical properties used (`margin-inline-start` instead of `margin-left`)
- [ ] Icons that imply direction (arrows, chevrons) flip for RTL
- [ ] Numbers display LTR even within RTL text (per Unicode bidi algorithm)
- [ ] Tables and lists adjusted for direction
---
## Typography
- [ ] Fonts support the script (not all fonts cover Cyrillic, CJK, Arabic, etc.)
- [ ] Font sizes adjusted if needed (some scripts read smaller; CJK often needs slightly larger)
- [ ] Line height appropriate (CJK often needs more)
- [ ] Word breaking handled (no breaking in the middle of CJK characters; break opportunities for Thai)
- [ ] Quotation marks correct ("..." in English, „..." in German, «...» in French, 「...」 in Japanese)
---
## Search and sort
- [ ] Search handles diacritics ("café" matches "cafe" or doesn't, by design)
- [ ] Sort order respects locale (German sorts ä with a, Swedish sorts ä after z)
- [ ] Search results in the same locale as the user (don't show English results to French users)
---
## Forms and inputs
- [ ] Input methods supported (IMEs for CJK, etc.)
- [ ] Pasting from clipboard works with non-Latin characters
- [ ] Field validation accepts non-Latin characters where appropriate (names should accept any Unicode)
- [ ] Min/max length constraints work for the script (Japanese names are often shorter; Arabic/Hebrew names use different character counts)
---
## Legal and compliance
- [ ] Privacy policy adapted to local laws (GDPR for EU, LGPD for Brazil, CCPA for California, etc.)
- [ ] Cookie consent matches local requirements
- [ ] Terms of service in local language and acknowledging local law
- [ ] Required disclaimers present (consumer protection, financial services, healthcare, etc.)
- [ ] Tax handling per locale (display inclusive in EU, exclusive in US, etc.)
- [ ] Local payment methods supported where customer expectations require
---
## Customer support and contact
- [ ] Support hours displayed in local timezone
- [ ] Support contact options match (phone numbers, chat, email, varies by region)
- [ ] Office address (if shown) is appropriate for the locale
- [ ] Local language support team or clear "support in [language]" indication
---
## Marketing and SEO
- [ ] Keyword research done in the local language (not just translated keywords)
- [ ] Meta titles and descriptions are locally compelling, not just translated
- [ ] Open Graph tags adapted (translated, locale-appropriate images)
- [ ] Schema.org markup translated where text-based
- [ ] Local search engines considered (Baidu in China, Yandex in Russia)
- [ ] Backlink strategy adapted to local web (local directories, local press)
---
## Testing per locale
- [ ] Page renders correctly in all major browsers
- [ ] Page renders correctly on mobile
- [ ] All links work and stay within the locale (or correctly switch locale)
- [ ] Forms submit correctly
- [ ] Confirmation flows work end-to-end (form → email → next step)
- [ ] No untranslated strings (search HTML for source-language strings)
- [ ] No broken images
- [ ] No layout breakage from longer or shorter text (German is often longer than English; CJK often shorter; Arabic similar to English in length but different layout)
- [ ] Performance comparable to default locale
---
## Language switcher
- [ ] Switcher visible on every page
- [ ] Available locales shown in their own language
- [ ] Current locale clearly indicated
- [ ] Switcher preserves the current page (not just sends to homepage)
- [ ] Switcher persists user choice (cookie or local storage)
- [ ] Switcher doesn't auto-redirect on first visit (suggests, doesn't force)
---
## Maintenance
- [ ] Translation update workflow defined
- [ ] Drift detection in place (when source changes, translation needs update)
- [ ] Per-locale analytics set up
- [ ] Per-locale error monitoring
- [ ] Translation quality reviewed periodically
- [ ] Locale sunset criteria defined (when to retire a poorly-performing locale)
---
## Per-locale metrics to watch
| Metric | Target |
|---|---|
| Page completion rate | Comparable to default locale |
| Form completion rate | Comparable to default locale |
| Bounce rate | Comparable to default locale |
| Time on page | Comparable to default locale |
| Conversion rate | Comparable to default locale |
| Translation freshness | Source content updates reflected within X days |
A locale persistently underperforming on user metrics may have:
- Translation quality issues
- Cultural mismatches in copy or imagery
- Missing local payment or contact options
- Slow performance from far hosting
- Unmet user expectations (US e-commerce conventions used in markets that prefer different patterns)
Investigate before scaling investment.
SKILL.md
---
name: internationalization
description: "Plan and run a multi-language or multi-region site. Use this skill when adding new locales, choosing URL structure for languages (subfolders vs subdomains vs ccTLDs), implementing hreflang, planning translation workflow, handling currency and date formats, designing for RTL languages, or auditing a stalled internationalization rollout. Triggers on internationalization, i18n, localization, l10n, hreflang, multi-language, translation workflow, RTL, locale, ccTLD, subfolder vs subdomain, language switcher. Also triggers when international audiences underperform or translations are stale."
category: cross-cutting
catalog_summary: "Locale strategy, hreflang, translation workflow, RTL design"
display_order: 3
---
# Internationalization
Add languages and regions in a way that works for users, search engines, and the team maintaining the content. Stack-agnostic.
---
## When to use
- Adding the first non-English (or non-default) language
- Adding additional locales to an existing internationalized site
- Choosing URL structure for languages
- Implementing hreflang tags
- Designing translation workflow
- Handling currency, date, time, and number formats
- Designing or fixing layout for RTL languages
- Auditing an internationalization rollout that's underperforming
## When NOT to use
- Single-language site (use other skills)
- Domain strategy that's not language-driven (use `domain-strategy`)
- Content strategy independent of locale (use `content-strategy`)
- Marketing copy production (use `content-and-copy`)
---
## Required inputs
- The locales in scope (language + region, e.g., `en-US`, `de-DE`, `fr-CA`)
- Business reason per locale (priority, audience size)
- Existing site architecture
- Translation resources (in-house, agency, AI-assisted, community)
- Content volume and update frequency
---
## The framework: 5 layers
Internationalization touches everything. Five layers, each with their own decisions.
### Layer 1: URL structure
How locales are reflected in URLs.
| Pattern | Example | When |
|---|---|---|
| ccTLD | example.de, example.fr | Strong country focus, distinct legal entities, willing to maintain separate domains |
| Subdomain | de.example.com, fr.example.com | Logical separation, willing to host separately, common for large sites |
| Subfolder | example.com/de/, example.com/fr/ | SEO equity unified, simplest to manage, default for most |
| URL parameter | example.com?lang=de | Avoid; weak SEO signal |
For most sites: subfolder is the default. Subdomain or ccTLD only when there's a specific reason (legal, infrastructure, or brand).
Within the chosen pattern, decide:
- Language only (`/de/`) or language plus region (`/de-de/`, `/de-at/`, `/de-ch/`)?
- Default locale: at the apex (`example.com`) or in a folder (`example.com/en/`)?
The default-locale-at-apex pattern is common but causes hreflang complexity (the apex needs an `x-default` and the canonical for the default language).
### Layer 2: Content structure
How content is organized across locales.
**Pattern A: Mirror.** Every page in every locale. The translation IS the page. Suitable for marketing sites with controlled content.
**Pattern B: Subset.** Some content in all locales, some only in select locales. Common for product pages (only available products), blog (some posts translated), or regulatory differences.
**Pattern C: Local.** Each locale has its own content largely independent of other locales. Common for media or community sites.
Most marketing sites are A. Most large sites end up at B by necessity. C is for sites with strong regional editorial.
The pattern affects:
- How content models are designed (does each piece have parent/translation relationships?)
- How translation is managed (workflow assumes the structure)
- How the team coordinates
### Layer 3: hreflang and canonicals
Telling search engines what's translated vs distinct.
**hreflang** specifies the language and optional region for each version.
```html
<link rel="alternate" hreflang="en-US" href="https://example.com/en-us/page">
<link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/page">
<link rel="alternate" hreflang="de-DE" href="https://example.com/de-de/page">
<link rel="alternate" hreflang="x-default" href="https://example.com/en-us/page">
```
Rules:
- Every page lists every translated equivalent (including itself)
- Pages must reciprocate (page A says page B is its German version; page B says page A is its English version)
- `x-default` is the fallback for users in unspecified regions
- Each page has its own canonical pointing to itself (not to the default language)
hreflang can be in the HTML head, in HTTP headers, or in the XML sitemap. Sitemap is best for large sites; HTML head is fine for small.
**Canonicals:**
- Self-referential per page
- Don't canonical the German page to the English page (search engines won't index the German page)
### Layer 4: Translation workflow
How content gets translated, kept fresh, and quality-controlled.
**Sources of translation:**
- In-house translators (full-time staff)
- Translation agency (paid per word, professional)
- Community contributors (volunteer, variable quality, free)
- AI-assisted plus human review (cheap, fast, growing in quality)
- AI only (acceptable for some content, not for brand-critical)
**Workflow stages:**
1. **Source content authored** in the source language
2. **Translation requested** through a TMS (translation management system) or spreadsheet
3. **Translation produced** with translation memory (avoids retranslating reused phrases)
4. **Review** by a second translator or in-region staff
5. **Localization** beyond translation (currency, units, examples, cultural references)
6. **Publishing** in the destination locale
7. **Update propagation** when source content changes
The TMS pays off above ~10K words of total content. Below that, spreadsheets and disciplined naming are fine.
**Update propagation is the hardest part.** Source content changes. Translations go stale. Without a process, you end up with locales drifting from the source.
### Layer 5: Locale-aware UX
Beyond translation, the experience must adapt.
**Currency:** display in the local currency where applicable. EUR for European locales, JPY for Japanese, etc. Don't show USD to French users for a French-locale page.
**Numbers:** thousand separators and decimals differ. `1,000.50` in en-US is `1.000,50` in de-DE.
**Dates and times:** format and order vary. `MM/DD/YYYY` in en-US, `DD/MM/YYYY` in en-GB, `YYYY-MM-DD` (ISO) is universal but unfamiliar to many.
**Names and addresses:** field order and required components differ. Country-aware address forms.
**Phone numbers:** E.164 international format universally; display formatting per locale.
**Units:** metric vs imperial. Most of the world is metric; the US is imperial. Some products serve both.
**Right-to-left (RTL) languages:** Arabic, Hebrew, Persian, Urdu. Layout flips: navigation moves right, text aligns right, icons that imply direction may flip too. CSS logical properties (`margin-inline-start` instead of `margin-left`) make this manageable.
**Language switcher:** prominent but not intrusive. Show locale names in their own language ("Deutsch" not "German"). Persist the choice. Don't auto-redirect based on browser language without offering a way back.
**Cultural sensitivity:** colors, imagery, examples, references that don't translate. Avoid hand gestures in product imagery. Avoid country-specific references unless localized.
---
## Workflow
### Step 1: Decide which locales
Don't add languages just because you can. Each locale has ongoing maintenance cost.
- Audience research: where are visitors and prospects?
- Business priority: which markets are growth targets?
- Content readiness: do you have the resources to maintain it?
- Legal: do regulations require localization (GDPR, accessibility laws)?
### Step 2: Pick URL structure
Subfolder for most. Document the choice and rationale.
### Step 3: Pick content structure
Mirror, subset, or local. Be honest about what's sustainable.
### Step 4: Set up hreflang and canonicals
Implement before launching the second locale, even if it's just one extra page.
### Step 5: Set up translation workflow
Pick a TMS or spreadsheet system. Document the workflow. Designate translators and reviewers.
### Step 6: Localize beyond translation
For each locale:
- Currency, numbers, dates, units
- Locale-specific images if needed
- Address forms
- Customer service hours and contact
### Step 7: Implement language switcher
- Prominent in the header or footer
- Shows the current locale clearly
- Lists all available locales in their own language
- Persists the choice (cookie or local storage)
- Doesn't auto-redirect based on browser; suggests instead
### Step 8: Test
- Each locale renders correctly
- hreflang links are valid (use a checker)
- Canonicals are self-referential per page
- Currency and dates are correct
- RTL layout is correct (for RTL locales)
- Language switcher works and persists
- Search-engine perspective: each locale is crawlable and indexable
### Step 9: Launch and monitor
Per locale:
- Indexing rate
- Traffic from intended geographies
- Engagement metrics in the locale
- Translation freshness (when did source content change without translation update?)
### Step 10: Maintain
- Translation update cadence (when source changes, when translations follow)
- Quarterly review of locale performance
- Sunset locales that aren't viable (better than maintaining a dead locale poorly)
---
## Failure patterns
**Auto-redirect based on browser language.** User is in Germany, prefers English. Site forces German. Frustrating. Suggest, don't redirect.
**Single canonical to default language.** Search engines can't index the translations. Self-canonical per page.
**Reciprocal hreflang missing.** German page lists English as its translation, English page doesn't list German. Search engines treat the relationship as unconfirmed.
**hreflang language without region when region matters.** `hreflang="es"` is fine if there's one Spanish version. If you have es-ES (Spain) and es-MX (Mexico), use both with regions.
**Auto-translated content treated as final.** Machine translation is an acceptable starting point. Human review is necessary for any user-facing content.
**Currency baked into copy.** "$99/month" in body text breaks for European users. Use templated currency that adapts.
**Hardcoded date formats.** "January 5, 2024" in code. Doesn't adapt. Use a date formatting library that respects locale.
**Field labels left in source language.** Translated body, untranslated form labels. Inconsistent. Translate UI strings as part of localization.
**Untranslated error messages.** User submits a form, gets an error in English on a French page. Frustrating. Translate UI states.
**Untranslated emails.** Site is in French; transactional emails are English. Translate emails to match.
**Forgotten locales in CMS.** Editors forget to update one locale. Drift. Use a TMS or workflow that surfaces drift.
**Locale switcher that doesn't work mid-flow.** User is on the German checkout, switches to French, lands on French homepage. Try to land on the same page in the new locale.
**RTL layouts that don't actually flip.** Margin and padding hardcoded for LTR. Use CSS logical properties.
**Sunset language without redirect.** Discontinuing French; old French URLs 404. Redirect to the closest equivalent in another supported language.
---
## Output format
An internationalization plan includes:
- **Locale list:** with priority and audience rationale
- **URL structure:** chosen pattern and reason
- **Content structure:** mirror, subset, or local
- **hreflang plan:** how it's implemented
- **Translation workflow:** sources, stages, tools
- **Localization checklist:** beyond translation (currency, dates, etc.)
- **Language switcher design:** position, behavior, persistence
- **Test plan:** what's verified per locale
- **Maintenance plan:** update cadence, drift detection
---
## Reference files
- [`references/locale-checklist.md`](references/locale-checklist.md): Per-locale checklist of everything that needs to adapt beyond translation, organized by category (URL, content, UX, format, legal).