Problem Statement / Feature Objective
The dashboard is currently English-only, but field operators in non-Anglophone regions (Latin America, EMEA, APAC) require localized UI for tariff labels, meter status messages, error toasts, and regulatory compliance notices. A runtime-switchable i18n framework must be implemented that loads locale JSON bundles on demand, handles pluralization rules (including Arabic, Polish, Russian), supports right-to-left (RTL) layout for Arabic/Hebrew, and localizes utility-specific concepts (tariff tiers, commodity units, billing periods) with correct regional formatting.
Technical Invariants & Bounds
- Locales: initial support for en-US, es-MX, pt-BR, fr-FR, de-DE, ar-SA, ja-JP, zh-CN (8 locales).
- Translation key count: ~500 keys across all UI surfaces.
- Bundle size target: each locale JSON file ≤ 15 KB gzipped. Loaded on-demand via dynamic import, never bundled in the initial JS chunk.
- Pluralization: support for CLDR plural rules (one, other for en; one, two, few, many, other for pl/ar; zero, one, two, few, many, other for ar).
- RTL support: flip layouts for ar-SA; use CSS logical properties (margin-inline-start, padding-inline-end) instead of physical directions (margin-left, padding-right).
- Number/currency formatting: use Intl.NumberFormat with region-specific units (kWh vs MWh, liters vs gallons, USD vs MXN vs EUR).
- Date/time formatting: use Intl.DateTimeFormat with locale-appropriate calendars (Gregorian, Japanese era, Islamic for ar-SA).
- Fallback chain:
locale → en-US → missing key warning in dev.
Codebase Navigation Guide
- src/i18n/locales/ — directory of JSON translation bundles, one per locale.
- src/i18n/config.ts — i18n configuration: supported locales, fallback, formatting options.
- src/i18n/useTranslation.ts — React hook:
t(key, params?) for string lookup, formatNumber(value, opts), formatDate(date, opts).
- src/i18n/I18nProvider.tsx — React context provider that loads locale bundles and sets
dir attribute on <html>.
- src/i18n/icu.ts — ICU MessageFormat parser for complex plural and gender rules.
- src/hooks/useLocale.ts — Hook that reads/sets
localStorage.locale and dispatches locale change.
- src/components/settings/LanguageSwitcher.tsx — Dropdown/flag selector in settings panel.
- src/utils/formatting.ts — Refactor existing number/date formatters to delegate to i18n.
Implementation Blueprint
- Set up the directory structure:
src/i18n/locales/en-US.json, es-MX.json, etc. Each file exports a flat map of keys to ICU MessageFormat strings.
- Implement
I18nProvider that reads the current locale from localStorage, dynamically imports the corresponding JSON bundle via import(/* webpackChunkName: "locale-[request]" */ ./locales/.json), and stores translations in a React context.
- Build
useTranslation hook returning { t, formatNumber, formatDate, locale, setLocale }. The t function parses ICU messages using intl-messageformat or a lightweight alternative.
- Apply RTL: on locale change, set
document.documentElement.dir = isRTL(locale) ? "rtl" : "ltr". Audit all CSS for physical direction properties and replace with logical equivalents.
- Create
LanguageSwitcher component in settings with a country-flag dropdown that calls setLocale.
- Write a script
scripts/extract-i18n-keys.ts that scans all t(...) calls in source and generates a skeleton JSON to send to translators.
- Add a Playwright test that switches to
es-MX, takes screenshots of all major routes, and verifies no t() keys are rendered as raw strings (missing translation detection).
Problem Statement / Feature Objective
The dashboard is currently English-only, but field operators in non-Anglophone regions (Latin America, EMEA, APAC) require localized UI for tariff labels, meter status messages, error toasts, and regulatory compliance notices. A runtime-switchable i18n framework must be implemented that loads locale JSON bundles on demand, handles pluralization rules (including Arabic, Polish, Russian), supports right-to-left (RTL) layout for Arabic/Hebrew, and localizes utility-specific concepts (tariff tiers, commodity units, billing periods) with correct regional formatting.
Technical Invariants & Bounds
locale → en-US → missing key warning in dev.Codebase Navigation Guide
t(key, params?)for string lookup,formatNumber(value, opts),formatDate(date, opts).dirattribute on<html>.localStorage.localeand dispatches locale change.Implementation Blueprint
src/i18n/locales/en-US.json,es-MX.json, etc. Each file exports a flat map of keys to ICU MessageFormat strings.I18nProviderthat reads the current locale fromlocalStorage, dynamically imports the corresponding JSON bundle viaimport(/* webpackChunkName: "locale-[request]" */ ./locales/.json), and stores translations in a React context.useTranslationhook returning{ t, formatNumber, formatDate, locale, setLocale }. Thetfunction parses ICU messages usingintl-messageformator a lightweight alternative.document.documentElement.dir = isRTL(locale) ? "rtl" : "ltr". Audit all CSS for physical direction properties and replace with logical equivalents.LanguageSwitchercomponent in settings with a country-flag dropdown that callssetLocale.scripts/extract-i18n-keys.tsthat scans allt(...)calls in source and generates a skeleton JSON to send to translators.es-MX, takes screenshots of all major routes, and verifies not()keys are rendered as raw strings (missing translation detection).