diff --git a/.planning/phases/34-i18n-foundation/34-04-SUMMARY.md b/.planning/phases/34-i18n-foundation/34-04-SUMMARY.md new file mode 100644 index 0000000..a07db92 --- /dev/null +++ b/.planning/phases/34-i18n-foundation/34-04-SUMMARY.md @@ -0,0 +1,111 @@ +--- +phase: 34-i18n-foundation +plan: 04 +subsystem: ui +tags: [react, i18n, react-i18next, settings, language-picker] + +# Dependency graph +requires: + - phase: 34-i18n-foundation plan 01 + provides: i18n infrastructure (i18next setup, locale files, settings.json keys) + - phase: 34-i18n-foundation plan 03 + provides: useLanguage hook returning persisted language preference from DB +provides: + - Language picker UI in settings page using pill-toggle pattern + - i18n language sync with persisted DB setting on app load + - Browser auto-detection on first visit via i18next LanguageDetector +affects: [34-i18n-foundation, any future localization work] + +# Tech tracking +tech-stack: + added: [] + patterns: + - Language picker uses same pill-toggle pattern as weight unit and currency pickers + - i18n sync via useEffect in RootLayout watching useLanguage() value + - Language labels use native names (English, Deutsch) for cross-language identification + +key-files: + created: [] + modified: + - src/client/routes/settings.tsx + - src/client/routes/__root.tsx + +key-decisions: + - "Language labels use native names (English, Deutsch) so users can identify their language even when UI is in another language" + - "DB is source of truth for language — useEffect in RootLayout syncs i18n to DB value if they differ" + - "Settings page calls both updateSetting.mutate and i18n.changeLanguage on click for immediate UI update plus persistence" + +patterns-established: + - "Language picker: pill-toggle pattern matching weight unit and currency pickers" + - "i18n sync: useEffect([language, i18n]) in RootLayout as safety net for DB/i18n drift" + +requirements-completed: [D-09, D-10, D-11, D-12] + +# Metrics +duration: 5min +completed: 2026-04-18 +--- + +# Phase 34 Plan 04: Language Picker & i18n Sync Summary + +**Language picker in settings using pill-toggle pattern, with i18n synced to DB setting on load and immediate UI update on change** + +## Performance + +- **Duration:** ~5 min (implementation was pre-existing at commit 46715cc) +- **Started:** 2026-04-18T00:00:00Z +- **Completed:** 2026-04-18T00:05:00Z +- **Tasks:** 2 +- **Files modified:** 2 + +## Accomplishments + +- Language picker (English/Deutsch) added to settings page above weight unit, using same pill-toggle pattern as weight unit and currency pickers +- Language change persists via `updateSetting.mutate({ key: "language", value })` and triggers immediate UI update via `i18n.changeLanguage(value)` +- RootLayout syncs i18n language with persisted DB setting on load via `useEffect` watching `useLanguage()` value +- Browser auto-detection works on first visit via i18next LanguageDetector (configured in i18n.ts from plan 01) +- Unknown browser locales fall back to English + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Add language picker to settings page** - `46715cc` (feat) +2. **Task 2: Sync i18n language with settings on app load** - `46715cc` (feat) + +**Plan metadata:** _(docs commit follows)_ + +_Note: Both tasks were committed together in a single pre-existing commit `46715cc feat(i18n): add language picker to settings and sync i18n with persisted preference`_ + +## Files Created/Modified + +- `src/client/routes/settings.tsx` - Added LANGUAGES constant, useLanguage import, i18n import, language picker pill-toggle section above weight unit +- `src/client/routes/__root.tsx` - Added useLanguage import, useEffect to sync i18n.changeLanguage with persisted language setting + +## Decisions Made + +- Language labels use native names ("English", "Deutsch") — not translated — so users can always identify their language regardless of current UI language +- DB setting is source of truth: `useEffect` in RootLayout syncs i18n to DB value if they differ on load +- Immediate feedback: settings page calls `i18n.changeLanguage()` directly in onClick alongside `updateSetting.mutate()` so language switches instantly without waiting for query invalidation + +## Deviations from Plan + +None - plan executed exactly as written. + +## Issues Encountered + +None. The implementation was already present at the correct commit. + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +- Language picker is live and functional in settings +- i18n syncs correctly between DB and runtime on load and change +- Ready for remaining i18n foundation work (translation content, German locale, etc.) + +--- +*Phase: 34-i18n-foundation* +*Completed: 2026-04-18*