ADR-0007: i18n strategy and language/region settings integration
Status
Accepted
Date
2026-03-03
Context
The product targets a German-speaking audience but must support English. The app must: - load translations by namespace - persist user language choice - keep user-facing formatting (date/number) aligned with language choices
Forces/constraints: - Consistency: translations must be organized predictably by namespace. - Maintainability: translation keys should be type-safe to prevent regressions. - UX: first impression should be German-first without blocking user choice.
Decision
We centralize i18n configuration and keep language/region controls in the settings UI:
- i18n init is centralized in:
frontend/src/i18n/index.ts- language detection order: localStorage → querystring → navigator
- German-first default on first visit via
localStoragekeyi18nextLng
- type safety is ensured via:
frontend/src/i18n/resources.d.ts(i18next module augmentation using JSON shapes)
- language/region settings are surfaced in the app menu:
frontend/src/app/HamburgerMenu/LanguageRegionSettings/*
- user preference sync is handled in settings context:
frontend/src/context/settings/SettingsContext.tsx(reacts toi18n.language)
Alternatives Considered
- Static build-time translations only
- Pros:
- No runtime network loading
- Cons:
- Less flexible; harder to add namespaces incrementally
- Pros:
- Untyped i18n keys (string keys everywhere)
- Pros:
- Fast to start
- Cons:
- Refactors break silently
- Harder to maintain large key sets
- Pros:
- Per-domain i18n configuration
- Pros:
- Domain autonomy
- Cons:
- Inconsistent detection/persistence behavior
- Pros:
Consequences
Positive
- German-first default aligns with target audience.
- Users can override and persist language choice.
- Translation keys and namespaces are safer to refactor.
- Settings can keep formatting aligned with language.
Negative / Tradeoffs
- Must keep JSON resources and
resources.d.tsin sync. - Requires discipline in namespace ownership (what belongs in
commonvs domain namespaces).
Implementation Notes
- Where it is implemented (paths, key modules)
- i18n boot:
frontend/src/i18n/index.ts - typing:
frontend/src/i18n/resources.d.ts - menu settings:
frontend/src/app/HamburgerMenu/LanguageRegionSettings/* - settings provider:
frontend/src/context/settings/SettingsContext.tsx
- i18n boot:
- Migration notes (if relevant)
- When adding a namespace, update both
I18N_NAMESPACESandresources.d.ts.
- When adding a namespace, update both
- Testing implications (what should be tested and where)
- i18n initialization and typing expectations:
frontend/src/__tests__/unit/i18n/*.
- i18n initialization and typing expectations:
References
- Architecture docs: Internationalization (i18n), Theme & Styling
- Diagram: i18n boot flow
- Related ADRs: ADR-0006