diff --git a/.planning/phases/34-i18n-foundation/34-08-SUMMARY.md b/.planning/phases/34-i18n-foundation/34-08-SUMMARY.md new file mode 100644 index 0000000..9929845 --- /dev/null +++ b/.planning/phases/34-i18n-foundation/34-08-SUMMARY.md @@ -0,0 +1,107 @@ +--- +phase: 34-i18n-foundation +plan: "08" +subsystem: i18n +tags: [i18n, german, locale, gap-closure] +dependency_graph: + requires: [34-06, 34-07] + provides: [german-locale-parity] + affects: [src/client/locales/de] +tech_stack: + added: [] + patterns: [json-locale-files, i18n-key-parity] +key_files: + created: [] + modified: + - src/client/locales/de/common.json + - src/client/locales/de/settings.json + - src/client/locales/de/threads.json + - src/client/locales/de/setups.json + - src/client/locales/de/collection.json +decisions: + - Used single quotes instead of German-style „ „ curly quotes in dangerZoneDescription to avoid JSON syntax errors +metrics: + duration: ~8 minutes + completed: 2026-04-18 + tasks_completed: 1 + tasks_total: 1 + files_modified: 5 +--- + +# Phase 34 Plan 08: German Translation Gap Closure Summary + +**One-liner:** Added 58 missing German translation keys across 5 de/*.json locale files to achieve full key parity with English, fixing fallback display for home, profile, threads, setups, and collection sections. + +## Objective + +Close the German translation gap identified in VERIFICATION.md — plans 34-06/34-07 wired useTranslation into routes and fixed umlaut encoding, but never added corresponding German translations for the new English keys. + +## Tasks Completed + +| Task | Name | Commit | Files | +|------|------|--------|-------| +| 1 | Add 58 missing German translations to 5 de/*.json files | 23172f7 | de/common.json, de/settings.json, de/threads.json, de/setups.json, de/collection.json | + +## Key Changes + +### de/common.json — 34 keys added +- `home.*` (3 keys): popularSetups, recentlyAdded, trendingCategories +- `imageUpload.*` (4 keys): clickToAdd, invalidType, tooLarge, uploadFailed +- `profile.*` (27 keys): full profile management section including account info, password management, danger zone + +### de/settings.json — 4 keys added +- `currency.suggestion`: currency region suggestion with `{{symbol}}` and `{{code}}` interpolation +- `currency.switch`: switch button label +- `showConversions.title` + `showConversions.description`: price conversion toggle + +### de/threads.json — 11 keys added +- `card.candidates` + `card.candidates_one`: pluralized candidate count with `{{count}}` interpolation +- `planning.*` (9 keys): full planning section with step-by-step guidance + +### de/setups.json — 3 keys added +- `card.by`: attributed author with `{{name}}` interpolation +- `card.anonymous`: anonymous attribution +- `impact.compareWith`: setup comparison prompt + +### de/collection.json — 6 keys added +- `tabs.setups`: setups tab label +- `totals.totalWeight` + `totals.totalCost`: totals bar labels +- `classificationBadge.base` + `classificationBadge.worn` + `classificationBadge.consumable`: classification badge labels + +## Verification + +``` +bun test tests/i18n/locales.test.ts +19 pass, 0 fail (previously 14 pass, 5 fail) +``` + +ASCII umlaut fallback check: 0 matches (no regressions). + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Fixed JSON syntax error from smart quotes in dangerZoneDescription** +- **Found during:** Task 1 — test run revealed `SyntaxError: JSON Parse error: Expected '}'` +- **Issue:** The German translation for `dangerZoneDescription` used German-style curly double-quotes `„Gelöschter Benutzer"` — the closing `"` (U+201C) was parsed by the JSON parser as the string-closing delimiter, causing a syntax error at line 115 +- **Fix:** Replaced curly quotes with straight single quotes: `'Gelöschter Benutzer'` +- **Files modified:** src/client/locales/de/common.json +- **Commit:** 23172f7 + +## Known Stubs + +None — all translation keys have real German text values, no placeholders. + +## Threat Flags + +None — plan modifies static bundled locale JSON files only. No network endpoints, auth paths, or schema changes introduced. + +## Self-Check: PASSED + +- [x] src/client/locales/de/common.json — exists and valid JSON +- [x] src/client/locales/de/settings.json — exists and valid JSON +- [x] src/client/locales/de/threads.json — exists and valid JSON +- [x] src/client/locales/de/setups.json — exists and valid JSON +- [x] src/client/locales/de/collection.json — exists and valid JSON +- [x] Commit 23172f7 exists +- [x] bun test tests/i18n/locales.test.ts: 19 pass, 0 fail diff --git a/src/client/locales/de/collection.json b/src/client/locales/de/collection.json index 8616990..66ccfad 100644 --- a/src/client/locales/de/collection.json +++ b/src/client/locales/de/collection.json @@ -27,5 +27,17 @@ "light": "Leicht", "medium": "Mittel", "heavy": "Schwer" + }, + "tabs": { + "setups": "Setups" + }, + "totals": { + "totalWeight": "Gesamtgewicht", + "totalCost": "Gesamtkosten" + }, + "classificationBadge": { + "base": "Basisgewicht", + "worn": "Getragen", + "consumable": "Verbrauchsmaterial" } } diff --git a/src/client/locales/de/common.json b/src/client/locales/de/common.json index 70c04f5..f96ab49 100644 --- a/src/client/locales/de/common.json +++ b/src/client/locales/de/common.json @@ -76,5 +76,45 @@ "showing": "{{filtered}} von {{total}} Gegenständen", "searchItems": "Gegenstände suchen...", "allCategories": "Alle Kategorien" + }, + "home": { + "popularSetups": "Beliebte Setups", + "recentlyAdded": "Kürzlich hinzugefügt", + "trendingCategories": "Beliebte Kategorien" + }, + "imageUpload": { + "clickToAdd": "Klicken, um Foto hinzuzufügen", + "invalidType": "Bitte wählen Sie ein JPG-, PNG- oder WebP-Bild.", + "tooLarge": "Das Bild muss kleiner als 5 MB sein.", + "uploadFailed": "Upload fehlgeschlagen. Bitte versuchen Sie es erneut." + }, + "profile": { + "title": "Profil", + "account": "Konto", + "accountInfo": "Ihre Kontoinformationen", + "email": "E-Mail", + "noEmail": "Keine E-Mail hinterlegt", + "change": "Ändern", + "newEmailPlaceholder": "Neue E-Mail-Adresse", + "updating": "Wird aktualisiert...", + "updateEmail": "E-Mail aktualisieren", + "emailUpdated": "E-Mail aktualisiert", + "memberSince": "Mitglied seit", + "security": "Sicherheit", + "managePassword": "Passwort verwalten", + "currentPassword": "Aktuelles Passwort", + "newPassword": "Neues Passwort", + "password": "Passwort", + "confirmPassword": "Passwort bestätigen", + "passwordRequirements": "Das Passwort muss mindestens 8 Zeichen mit Groß-, Kleinbuchstaben und einer Zahl enthalten.", + "passwordUpdated": "Passwort aktualisiert", + "changingPassword": "Wird geändert...", + "changePassword": "Passwort ändern", + "setPassword": "Passwort festlegen", + "dangerZone": "Gefahrenzone", + "dangerZoneDescription": "Löschen Sie Ihr Konto und alle persönlichen Daten. Öffentliche Setups werden als 'Gelöschter Benutzer' angezeigt.", + "deleteAccount": "Konto löschen", + "deleteConfirmMessage": "Diese Aktion ist dauerhaft. Geben Sie DELETE zur Bestätigung ein.", + "deleteConfirmPlaceholder": "DELETE zur Bestätigung eingeben" } } diff --git a/src/client/locales/de/settings.json b/src/client/locales/de/settings.json index aa6a9e2..fd30a98 100644 --- a/src/client/locales/de/settings.json +++ b/src/client/locales/de/settings.json @@ -10,7 +10,13 @@ }, "currency": { "title": "Währung", - "description": "Ändert das angezeigte Währungssymbol. Werte werden nicht umgerechnet." + "description": "Ändert das angezeigte Währungssymbol. Werte werden nicht umgerechnet.", + "suggestion": "Basierend auf Ihrer Region empfehlen wir {{symbol}} ({{code}})", + "switch": "Wechseln" + }, + "showConversions": { + "title": "Umgerechnete Preise anzeigen", + "description": "Zeigt ungefähre Umrechnungen an, wenn der lokale Preis nicht verfügbar ist" }, "apiKeys": { "title": "API-Schlüssel", diff --git a/src/client/locales/de/setups.json b/src/client/locales/de/setups.json index b193ff9..272e2a1 100644 --- a/src/client/locales/de/setups.json +++ b/src/client/locales/de/setups.json @@ -9,7 +9,9 @@ "items": "{{count}} Gegenstände", "items_one": "{{count}} Gegenstand", "weight": "Gewicht", - "price": "Preis" + "price": "Preis", + "by": "von {{name}}", + "anonymous": "Anonym" }, "share": { "title": "Setup teilen", @@ -38,6 +40,7 @@ "impact": { "title": "Auswirkungsvorschau", "adding": "Hinzufügen", - "removing": "Entfernen" + "removing": "Entfernen", + "compareWith": "Mit Setup vergleichen..." } } diff --git a/src/client/locales/de/threads.json b/src/client/locales/de/threads.json index 0fbe236..6f5ad70 100644 --- a/src/client/locales/de/threads.json +++ b/src/client/locales/de/threads.json @@ -41,5 +41,20 @@ "empty": { "noThreads": "Noch keine Recherche-Threads", "noCandidates": "Noch keine Kandidaten" + }, + "card": { + "candidates": "{{count}} Kandidaten", + "candidates_one": "{{count}} Kandidat" + }, + "planning": { + "title": "Planungs-Threads", + "emptyTitle": "Planen Sie Ihren nächsten Kauf", + "createFirst": "Erstellen Sie Ihren ersten Thread", + "step1Title": "Thread erstellen", + "step1Description": "Starten Sie einen Recherche-Thread für Ausrüstung, die Sie in Betracht ziehen", + "step2Title": "Kandidaten hinzufügen", + "step2Description": "Fügen Sie Produkte zum Vergleich mit Preisen und Gewichten hinzu", + "step3Title": "Gewinner wählen", + "step3Description": "Schließen Sie den Thread ab und der Gewinner wird Ihrer Sammlung hinzugefügt" } }