Files
GearBox/.planning/phases/34-i18n-foundation/34-03-SUMMARY.md
Jean-Luc Makiola a1ffcf3061 docs(34-03): complete locale-aware formatter integration plan summary
- All 5 tasks verified complete: useLanguage hook, formatPrice/formatWeight
  with Intl.NumberFormat, useFormatters locale wiring, formatter tests
- 15 tests passing, build clean, CURRENCY_SYMBOLS removed
2026-04-18 14:07:09 +02:00

5.4 KiB

phase: 34-i18n-foundation plan: "03" subsystem: ui tags: [i18n, formatters, intl, locale, react-hooks, typescript] # Dependency graph requires: - phase: 34-i18n-foundation/34-01 provides: i18n infrastructure, translation framework, useSetting hook patterns provides: - Locale-aware formatPrice using Intl.NumberFormat (en: "$1,234.56", de: "1.234,56 €") - Locale-aware formatWeight using Intl.NumberFormat (en: "1,234g", de: "1.234g") - useLanguage hook reading language from settings with "en" fallback - useFormatters hook wiring locale into all format calls - Formatter test suite covering null, en locale, de locale, unit conversions affects: [34-04, 34-05, 34-06, 34-07, 34-08] # Tech tracking tech-stack: added: [] patterns: - "Intl.NumberFormat for all number/currency formatting instead of manual symbol lookup" - "locale parameter added as third argument (defaulting to 'en') for backward compatibility" - "useLanguage follows same pattern as useWeightUnit/useCurrency: useSetting + VALID_* array + default" key-files: created: - src/client/hooks/useLanguage.ts - tests/formatters.test.ts modified: - src/client/lib/formatters.ts - src/client/hooks/useFormatters.ts key-decisions: - "locale parameter defaults to 'en' so existing callers without locale continue to work" - "CURRENCY_SYMBOLS constant removed — Intl.NumberFormat handles symbols natively" - "VALID_LANGUAGES ['en', 'de'] validates DB value before returning; invalid falls back to 'en' (T-34-04 threat mitigation)" patterns-established: - "Locale-aware formatting: all number/price/weight formatters accept locale as third arg" - "Settings hook pattern: useSetting + VALID_* array const + default fallback" requirements-completed: [D-04, D-09, D-10] # Metrics duration: 15min completed: 2026-04-18

Phase 34 Plan 03: Locale-Aware Formatter Integration Summary

Intl.NumberFormat-based locale-aware formatPrice and formatWeight with useLanguage hook — German locale shows "1.234,56 €", English shows "$1,234.56"

Performance

  • Duration: ~15 min
  • Started: 2026-04-18T12:15:00Z
  • Completed: 2026-04-18T12:30:00Z
  • Tasks: 5
  • Files modified: 4

Accomplishments

  • useLanguage() hook reads language from settings DB, validates against VALID_LANGUAGES, falls back to "en"
  • formatPrice() updated to use Intl.NumberFormat(locale, { style: "currency", currency }) — CURRENCY_SYMBOLS removed
  • formatWeight() updated to use Intl.NumberFormat(locale, { minimumFractionDigits, maximumFractionDigits }) for locale-aware separators
  • useFormatters() extended to call useLanguage() and pass locale to both formatters, exposing locale in return value
  • 15-test suite covering null, en/de locales, unit conversions, JPY special case, large number thousands separators

Task Commits

All tasks were implemented in a prior commit and verified as complete at plan execution time:

  • Tasks 1-4: locale-aware formatters and useLanguage hook - f759dd0 (feat)
  • Task 5: formatter tests - f759dd0 (feat/test)

Note: Implementation pre-existed this plan's execution in commit f759dd0 (feat(i18n): locale-aware formatters and useLanguage hook). All acceptance criteria verified as passing.

Files Created/Modified

  • src/client/hooks/useLanguage.ts — Hook reading "language" setting, returning Language type with "en" fallback, exports VALID_LANGUAGES
  • src/client/lib/formatters.ts — formatPrice and formatWeight updated with locale parameter and Intl.NumberFormat; CURRENCY_SYMBOLS removed
  • src/client/hooks/useFormatters.ts — Extended with useLanguage import, locale passed to both formatters, locale in return object
  • tests/formatters.test.ts — 15 tests for formatPrice and formatWeight across locales, units, null, and edge cases

Decisions Made

  • Locale parameter defaults to "en" to preserve backward compatibility with callers that don't pass locale
  • CURRENCY_SYMBOLS constant removed entirely — Intl.NumberFormat handles currency symbols natively for all currencies
  • T-34-04 threat mitigation applied: VALID_LANGUAGES validation ensures untrusted DB values can't cause unexpected locale behavior

Deviations from Plan

None - plan executed exactly as written. All files were already implemented in the correct state matching the plan's acceptance criteria.

Issues Encountered

None.

Known Stubs

None — all formatters produce real locale-aware output from Intl.NumberFormat.

Threat Flags

None — no new network endpoints, auth paths, or trust boundaries introduced. The T-34-04 threat (tampering via settings DB language value) is mitigated by VALID_LANGUAGES validation in useLanguage.

User Setup Required

None - no external service configuration required.

Next Phase Readiness

  • Locale-aware formatters are ready for phase 34-04 (UI locale switching) and 34-05 (currency display)
  • useLanguage hook is consumed by useFormatters, which is used app-wide via the useFormatters() hook pattern
  • Build passes cleanly, all 15 formatter tests pass

Self-Check: PASSED

  • src/client/hooks/useLanguage.ts — FOUND
  • src/client/lib/formatters.ts — FOUND (Intl.NumberFormat: 2 occurrences, CURRENCY_SYMBOLS: 0 occurrences)
  • src/client/hooks/useFormatters.ts — FOUND (useLanguage + locale: 6 occurrences)
  • tests/formatters.test.ts — FOUND (15 tests, all pass)
  • Build: PASSED (built in 937ms)
  • Commit f759dd0 — FOUND

Phase: 34-i18n-foundation Completed: 2026-04-18