diff --git a/.planning/phases/34-i18n-foundation/34-VERIFICATION.md b/.planning/phases/34-i18n-foundation/34-VERIFICATION.md new file mode 100644 index 0000000..edbc652 --- /dev/null +++ b/.planning/phases/34-i18n-foundation/34-VERIFICATION.md @@ -0,0 +1,164 @@ +--- +phase: 34-i18n-foundation +verified: 2026-04-17T20:45:00Z +status: gaps_found +score: 6/8 must-haves verified +overrides_applied: 0 +gaps: + - truth: "All new en keys added by plan 34-06 have corresponding de translations" + status: failed + reason: "Plan 34-06 added English keys to 5 namespaces but the corresponding German translations were never written to the de/* files. Plan 34-07 fixed existing ASCII fallbacks but did not add the missing keys. Result: 58 German keys are absent, causing `bun test tests/i18n/locales.test.ts` to fail with 5 failing namespaces." + artifacts: + - path: "src/client/locales/de/common.json" + issue: "Missing 34 keys: home.popularSetups, home.recentlyAdded, home.trendingCategories, imageUpload.clickToAdd, imageUpload.invalidType, imageUpload.tooLarge, imageUpload.uploadFailed, and all 27 profile.* keys" + - path: "src/client/locales/de/settings.json" + issue: "Missing 4 keys: currency.suggestion, currency.switch, showConversions.title, showConversions.description" + - path: "src/client/locales/de/threads.json" + issue: "Missing 11 keys: card.candidates, card.candidates_one, and all 9 planning.* keys" + - path: "src/client/locales/de/setups.json" + issue: "Missing 3 keys: card.by, card.anonymous, impact.compareWith" + - path: "src/client/locales/de/collection.json" + issue: "Missing 6 keys: tabs.setups, totals.totalWeight, totals.totalCost, classificationBadge.base, classificationBadge.worn, classificationBadge.consumable" + missing: + - "Add German translations for all 58 missing keys across de/common.json, de/settings.json, de/threads.json, de/setups.json, de/collection.json" + - "Ensure `bun test tests/i18n/locales.test.ts` passes (currently: 14 pass, 5 fail)" + - truth: "Key parity test passes after gap closure work" + status: failed + reason: "Test output: 14 pass, 5 fail — settings, threads, setups, collection, and common namespaces all have missing de keys. This directly contradicts the 34-06-SUMMARY claim of '19 pass, 0 fail'." + artifacts: + - path: "tests/i18n/locales.test.ts" + issue: "5 test failures due to missing German keys" + missing: + - "Fix the 58 missing German translations, then verify test passes" +--- + +# Phase 34: i18n Foundation — Verification Report (Gap-Closure Re-check) + +**Phase Goal:** Translation framework in place with string extraction, locale-aware formatting, and at least English + one additional language +**Verified:** 2026-04-17T20:45:00Z +**Status:** gaps_found +**Re-verification:** No — initial verification after gap closure plans 34-06 and 34-07 + +## Context + +Plans 34-01 through 34-05 completed the i18n framework in a prior session. UAT (34-UAT.md) identified one major issue: switching to German only translated the settings page, nav bar, and FAB — most of the UI remained in English and German text used ASCII umlaut approximations (ae/oe/ue). Gap-closure plans 34-06 and 34-07 were executed to address this. This verification checks whether that gap closure succeeded. + +## Must-Haves Derived + +The ROADMAP shows "TBD (discuss phase)" for success criteria. Must-haves are derived from: +1. The stated phase goal +2. The UAT gap description (primary driver for gap-closure plans) +3. Must-haves declared in 34-06-PLAN.md and 34-07-PLAN.md frontmatter + +**Derived truths:** + +| # | Source | Truth | +|---|--------|-------| +| 1 | 34-06 plan | Home page (routes/index.tsx) uses useTranslation and all UI chrome renders via t() calls | +| 2 | 34-06 plan | Setups list page (routes/setups/index.tsx) uses useTranslation and all UI chrome renders via t() calls | +| 3 | 34-06 plan | Profile page (routes/profile.tsx) uses useTranslation and all UI chrome renders via t() calls | +| 4 | 34-06 plan | Settings currency suggestion banner text renders via t() calls | +| 5 | 34-06 plan | All listed components have useTranslation imports and t() calls for every hardcoded English string | +| 6 | 34-06 plan | All new en keys have corresponding de translations with proper German umlauts | +| 7 | 34-07 plan | All German locale files use proper Unicode umlauts — no ASCII fallbacks | +| 8 | Both plans | Key parity test passes (bun test tests/i18n/locales.test.ts) | + +## Goal Achievement + +### Observable Truths + +| # | Truth | Status | Evidence | +|---|-------|--------|----------| +| 1 | Home page uses useTranslation with t() calls | VERIFIED | `grep -c useTranslation routes/index.tsx` → 4; t("home.popularSetups") etc. confirmed in file | +| 2 | Setups list page uses useTranslation | VERIFIED | `grep useTranslation routes/setups/index.tsx` → 1 import + 1 usage confirmed | +| 3 | Profile page uses useTranslation | VERIFIED | `grep -c useTranslation routes/profile.tsx` → 5; all account/security/danger zone sections wired | +| 4 | Settings currency suggestion uses t() calls | VERIFIED | `t("currency.suggestion", { symbol, code })` at line 298 of settings.tsx confirmed | +| 5 | All listed components have useTranslation wired | VERIFIED | ThreadTabs: 2, PlanningView: 2, TotalsBar: 2, ThreadCard: 2, PublicSetupCard: 2, SetupImpactSelector: 2, ClassificationBadge: 2, ImpactDeltaBadge: 2, ImageUpload: 2; DashboardCard correctly skipped (renders only caller-supplied props) | +| 6 | All new en keys have corresponding de translations | FAILED | Test output shows 58 German keys missing across 5 namespaces — see Gaps Summary | +| 7 | German locale files use proper Unicode umlauts | VERIFIED | `grep Loeschen\|Zurueck\|...` → 0 matches; umlaut counts: common=21, collection=4, settings=11 | +| 8 | Key parity test passes | FAILED | `bun test tests/i18n/locales.test.ts` → 14 pass, **5 fail** | + +**Score:** 6/8 truths verified + +### Required Artifacts + +| Artifact | Expected | Status | Details | +|----------|----------|--------|---------| +| `src/client/routes/index.tsx` | Translated home page | VERIFIED | 4 useTranslation calls, t("home.*") keys wired | +| `src/client/routes/setups/index.tsx` | Translated setups list | VERIFIED | useTranslation("setups") confirmed | +| `src/client/routes/profile.tsx` | Translated profile page | VERIFIED | 5 useTranslation calls, full profile section wired | +| `src/client/components/DashboardCard.tsx` | Translated dashboard card (or correctly skipped) | VERIFIED | No hardcoded strings — all strings passed as props from caller; skip documented in SUMMARY | +| `src/client/locales/de/common.json` | German common translations with proper umlauts | PARTIAL | Umlauts fixed; missing 34 keys added by plan 34-06 | +| `src/client/locales/de/collection.json` | German collection translations with proper umlauts | PARTIAL | Umlauts fixed; missing 6 keys: tabs.setups, totals.totalWeight, totals.totalCost, classificationBadge.{base,worn,consumable} | +| `src/client/locales/de/settings.json` | German settings with proper umlauts | PARTIAL | Umlauts fixed; missing 4 keys: currency.suggestion, currency.switch, showConversions.{title,description} | +| `src/client/locales/de/threads.json` | German thread translations with proper umlauts | PARTIAL | Umlauts fixed; missing 11 keys: card.candidates, card.candidates_one, planning.* (9 keys) | +| `src/client/locales/de/setups.json` | German setup translations with proper umlauts | PARTIAL | Umlauts fixed; missing 3 keys: card.by, card.anonymous, impact.compareWith | + +### Key Link Verification + +| From | To | Via | Status | Details | +|------|----|-----|--------|---------| +| `routes/index.tsx` | `locales/en/common.json` | `useTranslation("common")` | WIRED | t() calls present for home.* keys | +| `components/TotalsBar.tsx` | `locales/en/collection.json` | `useTranslation("collection")` | WIRED | 2 useTranslation calls confirmed | +| `components/PlanningView.tsx` | `locales/en/threads.json` | `useTranslation(["threads","common"])` | WIRED | planning.* keys used in component | +| `lib/i18n.ts` | `locales/de/common.json` | `import deCommon` | WIRED | File exists and is valid JSON | + +### Data-Flow Trace (Level 4) + +Not applicable — locale files are static bundled content. i18next loads them at initialization, not via dynamic data fetch. + +### Behavioral Spot-Checks + +| Behavior | Command | Result | Status | +|----------|---------|--------|--------| +| Build succeeds | `bun run build` | `built in 872ms` with no errors | PASS | +| Locale parity test | `bun test tests/i18n/locales.test.ts` | 14 pass, 5 fail (settings, threads, setups, collection, common) | FAIL | + +### Requirements Coverage + +Plan 34-06 claims requirements D-01, D-02, D-03. Plan 34-07 claims D-13, D-14. These are phase-internal requirement IDs not mapped in REQUIREMENTS.md (which tracks v2.1 milestone requirements only). Coverage assessed from phase context: + +| Requirement | Description | Status | Evidence | +|-------------|-------------|--------|----------| +| D-01 | All UI strings extractable / use t() | PARTIAL | Routes and components wired; de translations incomplete for new keys | +| D-02 | German language available | PARTIAL | German locale exists; missing 58 keys means German UI has fallback gaps | +| D-03 | Locale-aware formatting | VERIFIED | Currency and number formatting via Intl confirmed in prior plans | +| D-13 | Proper German umlauts | VERIFIED | All ASCII fallbacks replaced in 6 de/*.json files | +| D-14 | Natural German phrasing | VERIFIED | onboarding.json improved; German text reads naturally where it exists | + +### Anti-Patterns Found + +| File | Line | Pattern | Severity | Impact | +|------|------|---------|----------|--------| +| `de/common.json` | — | Missing `home.*`, `imageUpload.*`, `profile.*` sections entirely | Blocker | German users see English fallbacks for home page, image upload errors, and entire profile page | +| `de/settings.json` | — | Missing `currency.suggestion`, `currency.switch`, `showConversions.*` | Blocker | German users see English text for currency suggestion banner and price conversion toggle | +| `de/threads.json` | — | Missing `card.*` and `planning.*` sections | Blocker | German users see English for thread card labels and entire planning empty state | +| `de/setups.json` | — | Missing `card.by`, `card.anonymous`, `impact.compareWith` | Blocker | German users see English for setup card attribution and compare selector | +| `de/collection.json` | — | Missing `tabs.setups`, `totals.*`, `classificationBadge.*` | Blocker | German users see English for collection tabs, totals bar, and classification badges | + +### Human Verification Required + +None — all gaps are verifiable programmatically. The key parity test is the authoritative check. + +### Gaps Summary + +**Root cause:** Plan 34-06 successfully wired `useTranslation` into all routes and components, and added the required English keys to all 5 namespaces. However, the corresponding German translations were not written to the de/*.json files. Plan 34-07 then corrected ASCII umlaut fallbacks in the existing German locale content, but did not add the new missing keys because they simply were not there to correct. + +The 34-06-SUMMARY.md incorrectly claims "19 pass, 0 fail" for the key parity test. The actual current state shows 5 failing namespaces with 58 missing German translations. This gap means: + +- German users browsing the home page see English section headings +- German users on the profile page see entirely English content +- The settings currency suggestion banner, thread cards, setup cards, totals bar, and classification badges all fall back to English +- The i18n framework goal of "at least English + one additional language" is technically met structurally but practically incomplete — German coverage has material gaps in 5 of 6 namespaces + +**Two gaps block goal achievement:** + +1. **58 missing German translation keys** across de/common.json, de/settings.json, de/threads.json, de/setups.json, de/collection.json +2. **Key parity test fails** (5 namespaces) — the project's own contract for locale completeness is violated + +These two gaps have a single root cause and a single fix: add the missing German translations to all 5 de/*.json files. + +--- + +_Verified: 2026-04-17T20:45:00Z_ +_Verifier: Claude (gsd-verifier)_