Files
GearBox/.planning/phases/34-i18n-foundation/34-06-SUMMARY.md

7.1 KiB

phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics, requirements
phase plan subsystem tags dependency_graph tech_stack key_files decisions metrics requirements
34-i18n-foundation 06 client/i18n
i18n
react-i18next
localization
german
components
routes
requires provides affects
34-01
34-02
34-05
fully-wired-i18n-components
translated-routes
client/routes/index
client/routes/profile
client/routes/settings
client/components/*
added patterns
useTranslation with namespace arrays
plural keys with count interpolation
t() with defaultValue fallback
created modified
src/client/routes/index.tsx
src/client/routes/profile.tsx
src/client/routes/settings.tsx
src/client/components/ThreadTabs.tsx
src/client/components/PlanningView.tsx
src/client/components/TotalsBar.tsx
src/client/components/ThreadCard.tsx
src/client/components/PublicSetupCard.tsx
src/client/components/SetupImpactSelector.tsx
src/client/components/ClassificationBadge.tsx
src/client/components/ImpactDeltaBadge.tsx
src/client/components/ImageUpload.tsx
src/client/locales/en/common.json
src/client/locales/en/collection.json
src/client/locales/en/setups.json
src/client/locales/en/settings.json
src/client/locales/en/threads.json
src/client/locales/de/common.json
src/client/locales/de/collection.json
src/client/locales/de/setups.json
src/client/locales/de/settings.json
src/client/locales/de/threads.json
DashboardCard skipped: component renders only props (title, stats, emptyText) with no hardcoded UI strings — caller is responsible for translation
ClassificationBadge uses t() with defaultValue fallback instead of static lookup map — handles unknown classification values gracefully
Intl.DateTimeFormat locale changed from hardcoded 'en-US' to undefined in profile.tsx — uses browser locale for member-since date formatting
threads.empty.noThreads changed from 'No research threads yet' to 'No threads found' to match PlanningView filtered-results context
duration completed tasks_completed files_modified
~30 minutes 2026-04-17T18:26:54Z 2 22
D-01
D-02
D-03

Phase 34 Plan 06: i18n Gap Closure — Routes and Components Summary

Wired useTranslation into all routes and components that had hardcoded English strings, closing the UAT-identified gap where only the settings page, nav bar, and FAB were translated.

What Was Built

Task 1 — Routes and settings currency suggestion (commit 755c0ab):

  • routes/index.tsx: Section headings (Popular Setups, Recently Added, Trending Categories) now use t("home.*") from common namespace
  • routes/profile.tsx: All sections (Account, Security, Danger Zone) fully translated — email management, password change, account deletion flow
  • routes/settings.tsx: Currency suggestion banner text uses t("currency.suggestion", { symbol, code }) with interpolation; Switch button and Dismiss aria-label use t()
  • Added home, profile, imageUpload sections to en/de common.json
  • Added currency.suggestion, currency.switch, showConversions to en/de settings.json

Task 2 — 10 remaining components (commit 480abdd):

  • ThreadTabs.tsx: Tab labels (My Gear → Gear, Planning, Setups) via collection namespace
  • PlanningView.tsx: Section heading, active/resolved tabs, full empty state (title + 3 steps + CTA), "No threads found" — via threads namespace
  • TotalsBar.tsx: "Sign in" link via common.auth.signIn
  • ThreadCard.tsx: "Resolved" badge and candidate count with plural form ({{count}} candidates / {{count}} candidate)
  • PublicSetupCard.tsx: "by {{name}}" and "Anonymous" fallback; item count with plural form
  • SetupImpactSelector.tsx: "Compare with setup..." placeholder option
  • ClassificationBadge.tsx: base/worn/consumable labels via collection.classificationBadge.* with defaultValue fallback
  • ImpactDeltaBadge.tsx: "(add)" mode label via setups.impact.adding
  • ImageUpload.tsx: "Click to add photo", invalid type error, file too large error, upload failed error
  • DashboardCard.tsx: Correctly skipped — all strings are props from caller

New Locale Keys Added

en/de common.json: home.{popularSetups,recentlyAdded,trendingCategories}, imageUpload.{clickToAdd,invalidType,tooLarge,uploadFailed}, profile.{title,account,accountInfo,email,noEmail,change,newEmailPlaceholder,updating,updateEmail,emailUpdated,memberSince,security,managePassword,currentPassword,newPassword,password,confirmPassword,passwordRequirements,passwordUpdated,changingPassword,changePassword,setPassword,dangerZone,dangerZoneDescription,deleteAccount,deleteConfirmMessage,deleteConfirmPlaceholder}

en/de settings.json: currency.{suggestion,switch}, showConversions.{title,description}

en/de collection.json: tabs.setups, totals.{totalWeight,totalCost}, classificationBadge.{base,worn,consumable}

en/de setups.json: card.{by,anonymous}, impact.compareWith

en/de threads.json: card.{candidates,candidates_one}, planning.{title,emptyTitle,createFirst,step1Title,step1Description,step2Title,step2Description,step3Title,step3Description}

Deviations from Plan

Auto-fixed Issues

1. [Rule 1 - Bug] Fixed hardcoded en-US locale in profile.tsx date formatting

  • Found during: Task 1
  • Issue: Intl.DateTimeFormat("en-US", ...) for "Member since" date used hardcoded locale
  • Fix: Changed to Intl.DateTimeFormat(undefined, ...) to use browser's locale
  • Files modified: src/client/routes/profile.tsx

2. [Rule 2 - Missing] Fixed ASCII fallbacks in de/common.json filter section

  • Found during: Task 1 locale update
  • Issue: Existing de/common.json had "Gegenstaenden" instead of "Gegenständen" in filter.showing
  • Fix: Updated to use proper umlauts when touching those strings
  • Files modified: src/client/locales/de/common.json

Verification

  • grep -c "useTranslation" src/client/routes/index.tsx → 4
  • grep -c "useTranslation" src/client/routes/profile.tsx → 5
  • grep -c "useTranslation" src/client/routes/settings.tsx → 1 (already had it)
  • All 10 components (minus DashboardCard which has no hardcoded strings) have useTranslation
  • bun run build passes with no errors
  • bun test tests/i18n/locales.test.ts → 19 pass, 0 fail

Commits

Task Commit Description
Task 1 755c0ab feat(34-06): wire useTranslation into routes and settings currency suggestion
Task 2 480abdd feat(34-06): wire useTranslation into 10 remaining components

Known Stubs

None — all translated strings are wired to real locale data.

Threat Flags

None — translation strings are static bundled content, not user input. React JSX escaping prevents XSS per T-34-07.

Self-Check: PASSED

  • src/client/routes/index.tsx: exists, contains useTranslation
  • src/client/routes/profile.tsx: exists, contains useTranslation
  • src/client/routes/settings.tsx: exists, contains useTranslation
  • All 10 components modified: confirmed via grep
  • Commits 755c0ab and 480abdd: confirmed in git log
  • Build: passed
  • i18n parity tests: 19/19 passed