Skip to content

Internationalization (i18n) Framework for Multi-Lingual Utility Dashboard with Runtime Language Switching #68

Description

@elizabetheonoja-art

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

  1. 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.
  2. 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.
  3. Build useTranslation hook returning { t, formatNumber, formatDate, locale, setLocale }. The t function parses ICU messages using intl-messageformat or a lightweight alternative.
  4. 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.
  5. Create LanguageSwitcher component in settings with a country-flag dropdown that calls setLocale.
  6. Write a script scripts/extract-i18n-keys.ts that scans all t(...) calls in source and generates a skeleton JSON to send to translators.
  7. 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).

Metadata

Metadata

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official Campaign

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions