- Home
- Skills
- Code Review
- Internationalization Review
Internationalization Review
Review i18n implementation: hard-coded strings, RTL support, date and number formatting, and pluralization rules.
The Problem
Internationalization bolted on after launch is ten times more expensive than building it in from the start. Hard-coded strings hide in error messages, tooltips, aria-labels, and email templates. Date formatting that works in the US breaks in Germany (1/2/2026 is January 2nd or February 1st?). Layouts designed for English collapse when German text is 30% longer or Arabic text flows right-to-left. Pluralization rules assumed to be “one vs. many” fail in languages with 6 plural forms like Arabic.
The Prompt
Review the following code for internationalization readiness. Act as an i18n specialist preparing this application for launch in 5 additional languages.
FRAMEWORK: [e.g., React + react-i18next, Vue + vue-i18n, Astro, Next.js]
CURRENT LANGUAGES: [e.g., English only, English + German]
TARGET LANGUAGES: [e.g., German, French, Arabic (RTL), Japanese, Portuguese]
CODE:
[paste component code and i18n configuration]
TRANSLATION FILES (if any):
[paste locale JSON/YAML files]
Evaluate across these dimensions:
1. **String Externalization**
- Are all user-visible strings extracted into translation files?
- Check: button labels, error messages, placeholders, aria-labels, page titles
- Are there string concatenations that break in other languages?
(e.g., "Welcome, " + name — in Japanese, name comes first)
- Are alt texts and SEO meta tags translatable?
2. **Formatting**
- Are dates formatted with Intl.DateTimeFormat (not manual formatting)?
- Are numbers formatted with Intl.NumberFormat (decimal separators vary)?
- Are currencies displayed correctly (symbol position varies by locale)?
- Are units (km/miles, kg/lbs) locale-aware?
3. **Pluralization**
- Does the i18n library handle plural rules beyond "one/other"?
- Are plural forms provided for all supported languages?
- Are there manual `count === 1 ? "item" : "items"` patterns (breaks in Russian, Arabic)?
4. **Layout & RTL**
- Do layouts use logical properties (margin-inline-start, not margin-left)?
- Is the `dir` attribute set on the HTML element?
- Do icons with directional meaning flip for RTL (arrows, progress bars)?
- Does text expansion (German +30%, Thai +50%) break layouts?
5. **Translation Quality**
- Are translation keys semantic (user.greeting, not text_1)?
- Is context provided for translators (comments in translation files)?
- Are there translations that look machine-translated or truncated?
- Are gendered forms handled where needed?
6. **Technical Setup**
- Is locale detection implemented (URL, cookie, browser preference)?
- Are locale-specific URLs set up for SEO (hreflang, canonical)?
- Is the language switcher accessible and visible?
- Are API responses localized (error messages, enum labels)?
For each issue, provide:
- **Location**: File and line or translation key
- **Severity**: broken-in-locale (will fail for some languages) / incomplete / improvement
- **Affected Languages**: Which languages this impacts
- **Fix**: i18n-correct code
Example Output
## i18n Review: 6 issues found
### Broken in Locale: Concatenated String
Location: src/components/Greeting.tsx:5
Code: `<h1>{"Welcome to " + city + "!"}</h1>`
Problem: Word order differs by language. German: "Willkommen in Berlin!"
Japanese: "ベルリンへようこそ!" — city comes in the middle, not appended.
Fix: Use interpolation:
t('greeting.welcome', { city }) → "Welcome to {{city}}!"
de: "Willkommen in {{city}}!" / ja: "{{city}}へようこそ!"
### Broken in Locale: Manual Date Formatting
Location: src/utils/format.ts:12
Code: `${month}/${day}/${year}` — MM/DD/YYYY is US-only.
Fix:
new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'long', day: 'numeric' }).format(date)
// en-US: "April 15, 2026" / de-DE: "15. April 2026" / ja-JP: "2026年4月15日"
### Broken in Locale: Hardcoded Pluralization
Location: src/components/Cart.tsx:23
Code: `${count} item${count !== 1 ? 's' : ''}`
Affected: Russian (6 forms), Arabic (6 forms), Polish (3 forms)
Fix: Use i18n plural rules:
t('cart.items', { count }) with ICU MessageFormat:
"{count, plural, one {# item} other {# items}}"
When to Use
Run this before adding a second language to any application, when auditing an existing multilingual app for quality, or when preparing to enter RTL markets (Arabic, Hebrew). Essential at the start of any project that might eventually need localization — it is far cheaper to build i18n-ready from day one than to retrofit later.
Pro Tips
- Test with extreme languages — German (long words), Japanese (no spaces), Arabic (RTL + different digits) expose the most i18n bugs in a single pass.
- Use pseudo-localization — ask “Generate a pseudo-locale file that doubles all string lengths and adds accents (e.g., Weeelcooomee) to test layout resilience.”
- Check the full surface — email templates, PDF generation, push notifications, and error logs are commonly missed when extracting strings.
- Review hreflang tags — for SEO, ask “Verify all hreflang tags are correct and form a complete bidirectional link set across all locales.”