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
This commit is contained in:
130
.planning/phases/34-i18n-foundation/34-03-SUMMARY.md
Normal file
130
.planning/phases/34-i18n-foundation/34-03-SUMMARY.md
Normal file
@@ -0,0 +1,130 @@
|
||||
---
|
||||
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*
|
||||
Reference in New Issue
Block a user