software-localisation
Production-grade i18n/l10n for React, Vue, Angular, and Next.js with ICU format and RTL support. Use when setting up or debugging localisation.
What this skill does
# Software Localisation - Quick Reference
Production patterns for internationalisation (i18n) and localisation (l10n) in modern web applications. Covers library selection, translation management, ICU message format, RTL support, and CI/CD workflows.
**Snapshot (2026-02)**: i18next 25.x, react-i18next 16.x, react-intl 8.x, vue-i18n 11.x, next-intl 4.x, @angular/localize 21.x. Always verify current versions in the target repo (see Currency Check Protocol).
**Authoritative References**:
- [i18next Documentation](https://www.i18next.com/)
- [FormatJS/react-intl](https://formatjs.github.io/)
- [ICU Message Format](https://unicode-org.github.io/icu/userguide/format_parse/messages/)
- [MDN Intl API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)
## Quick Reference
| Task | Tool/Library | Command | When to Use |
|------|--------------|---------|-------------|
| React i18n | react-i18next | `npm i i18next react-i18next` | Most React apps, flexibility |
| React i18n (ICU) | react-intl (FormatJS) | `npm i react-intl` | ICU-first message catalog + tooling |
| Vue i18n | vue-i18n | `npm i vue-i18n` | Vue 3 apps |
| Angular i18n | @angular/localize | `ng add @angular/localize` | Angular apps |
| Next.js i18n | next-intl | `npm i next-intl` | Next.js App Router |
| Minimal bundle | LinguiJS | `npm i @lingui/core @lingui/react` | Bundle size critical |
| Type-safe | typesafe-i18n | `npm i typesafe-i18n` | TypeScript-first projects |
| String extraction | i18next-parser | `npx i18next-parser` | Extract keys from code |
| ICU linting | @formatjs/cli | `npx formatjs extract` | Validate ICU messages |
## Decision Tree: Library Selection
```text
Project requirements:
│
├─ React/Next.js project?
│ ├─ ICU-first message catalogs + FormatJS tooling?
│ │ └─ react-intl (FormatJS)
│ │
│ ├─ Flexibility, plugins, lazy loading?
│ │ └─ react-i18next
│ │
│ ├─ Bundle size critical?
│ │ └─ LinguiJS (ICU syntax)
│ │
│ └─ TypeScript-first, compile-time safety?
│ └─ typesafe-i18n
│
├─ Vue/Nuxt project?
│ └─ vue-i18n (Composition API)
│
├─ Angular project?
│ ├─ Built-in solution preferred?
│ │ └─ @angular/localize (first-party, AOT support)
│ │
│ └─ Need i18next ecosystem?
│ └─ angular-i18next (wrapper)
│
└─ Framework-agnostic / Node.js?
└─ i18next core (works everywhere)
```
## Library Comparison
| Library | ICU Support | Lazy Loading | TypeScript | Best For |
|---------|-------------|--------------|------------|----------|
| react-i18next | Plugin/optional | Native | Good | Flexible, popular React choice |
| react-intl | Native | Manual | Good | ICU-first catalogs + tooling |
| LinguiJS | Native | Native | Excellent | Bundle-conscious apps |
| typesafe-i18n | Limited | Manual | Excellent | Compile-time key safety |
| vue-i18n | Native | Native | Good | Vue 3 apps |
| @angular/localize | Native | AOT | Native | Angular apps |
## Core Concepts
### Character Encoding (Critical)
**Always use UTF-8** across your entire stack to prevent text corruption:
```text
PASS Required: UTF-8 everywhere
- Database: utf8mb4 (MySQL) or UTF-8 (PostgreSQL)
- HTML: <meta charset="UTF-8">
- HTTP headers: Content-Type: text/html; charset=utf-8
- File encoding: Save all source files as UTF-8
- API responses: JSON with UTF-8 encoding
```
UTF-8 supports all Unicode characters including emojis, mathematical symbols, and all language scripts. Inconsistent encoding causes: corrupted characters (�), failed searches for accented names, and rejected international input.
### Translation Key Patterns
```typescript
// Flat keys (simple)
"welcome": "Welcome to our app"
"user.greeting": "Hello, {name}"
// Nested keys (organised)
{
"user": {
"greeting": "Hello, {name}",
"profile": {
"title": "Your Profile"
}
}
}
// Namespace separation (scalable)
// common.json, auth.json, dashboard.json
```
### ICU Message Format Essentials
```text
// Simple interpolation
"Hello, {name}!"
// Pluralisation
"{count, plural, one {# item} other {# items}}"
// Select (gender, category)
"{gender, select, male {He} female {She} other {They}} liked your post"
// Number formatting
"Price: {price, number, currency}"
// Date formatting
"Posted: {date, date, medium}"
```
### Locale Detection Strategy
```text
Priority order:
1. User preference (stored in profile/localStorage)
2. URL parameter or path (/en/about, ?lang=de)
3. Cookie (NEXT_LOCALE, i18next)
4. Accept-Language header
5. Default locale fallback
```
## Locale Quality Gates (SEO/AEO-Safe)
Use these gates for locale-routed, indexable pages (for example `/vi/*`, `/de/*`):
- Do not ship mixed-language content on a single locale route.
- Do not silently fall back to English for indexable page content.
- Keep metadata, breadcrumbs, and JSON-LD in the same locale as visible content.
- Prefer explicit missing-key handling in CI over runtime fallback in production SEO pages.
- If fallback is unavoidable, use locale-safe neutral copy and track missing keys.
### Missing Translation Decision Rule
- Marketing/SEO pages: block publish or replace with locale-safe copy; never inject English fragments.
- Product UI (non-indexed surfaces): fallback is acceptable with telemetry and follow-up fix.
## EN/RU Mixed-Language Regression Protocol
Use this when users report locale mixing (for example RU screens showing EN fragments).
### 1) Key-Parity Diff (Base vs Target Locale)
Compare key sets between source and target locale files; treat missing keys as release blockers on user-facing pages.
```bash
jq -r 'paths(scalars) | join(".")' app/src/messages/en/*.json | sort -u > /tmp/en.keys
jq -r 'paths(scalars) | join(".")' app/src/messages/ru/*.json | sort -u > /tmp/ru.keys
comm -23 /tmp/en.keys /tmp/ru.keys # present in EN, missing in RU
```
### 2) Hardcoded-String Sweep in UI
Search for user-visible literals in components/pages that should use i18n keys.
```bash
rg -n '>[A-Za-z][^<]{2,}<' app/src -g '*.tsx'
rg -n '"[A-Za-z][^"]{2,}"' app/src -g '*.tsx' -g '*.ts'
```
### 3) Route-Level Locale Smoke Check
For target locale routes, verify rendered text is consistently localized and no fallback EN fragments appear in critical UI regions.
### 4) Engine Text Audit
Ensure computed/engine-driven messages (not just static labels) pass through translation mapping instead of returning raw EN strings.
### 5) CI Gate
Add a lightweight gate that fails when:
- required target-locale keys are missing,
- newly added UI literals bypass the i18n layer,
- locale-routed smoke pages include mixed-language sentinel terms.
### Runtime Constraint Note
If an agent runtime has no external translation connector, do not block on auto-translation tools. Enforce key completeness + placeholder strategy, then backfill approved translations in a separate tracked pass.
## Engine Output i18n (`_i18n` Metadata Pattern)
Server-generated engine content (astrology calculations, ML outputs, computed reports) needs localisation without making the engine locale-aware.
### Pattern
- Engine attaches `_i18n: { key: "transits.neptune_trine.description", params: { planet: "Neptune" } }` alongside the English string
- Client resolves: `_i18n ? t(_i18n.key, _i18n.params) : englishFallback`
- Backward-compatible: old cached responses without `_i18n` gracefully degrade to English
- Server caches once; every locale resolves on the client
- Use `t.has(key)` before `t(key)` for graceful fallback
| Pattern | Status | Why |
|---------|--------|-----|
| `{ text: "Neptune trine Jupiter", _i18n: { key: "transits.neptune_trine", params: { p1: "Neptune", p2: "Jupiter" } } }` | PASS | Client resolves per locale; server caches once |
| `{ text_en: "...", text_ru: "...", text_de: "..." }` | FAIL | Server bloat, cache per locale |
| `t(meaning.theme)` | FAIL | Using raw engine output as translation key |
| `t.Related in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.