--- phase: 34-i18n-foundation plan: 07 type: execute wave: 4 depends_on: [05] files_modified: - src/client/locales/de/common.json - src/client/locales/de/collection.json - src/client/locales/de/threads.json - src/client/locales/de/setups.json - src/client/locales/de/onboarding.json - src/client/locales/de/settings.json autonomous: true gap_closure: true requirements: [D-13, D-14] must_haves: truths: - "All German locale files use proper umlauts (ä, ö, ü, Ä, Ö, Ü, ß) instead of ASCII fallbacks (ae, oe, ue)" - "No instances of 'Loeschen', 'Zurueck', 'Bestaetigen', 'Schliessen', 'Gegenstaende', 'Ausruestung', 'Waehrung', 'Schluessel' remain" - "German translations read naturally to a German speaker" - "Key parity test still passes after corrections" artifacts: - path: "src/client/locales/de/common.json" provides: "German common translations with proper umlauts" contains: "Löschen" - path: "src/client/locales/de/collection.json" provides: "German collection translations with proper umlauts" contains: "Gegenstände" - path: "src/client/locales/de/settings.json" provides: "German settings translations with proper umlauts" contains: "Währung" key_links: - from: "src/client/lib/i18n.ts" to: "src/client/locales/de/common.json" via: "import deCommon" pattern: "deCommon" --- Fix all German locale files to use proper Unicode umlauts instead of ASCII fallbacks. Purpose: UAT test 4 reported that German text uses "ae" instead of "ä", "oe" instead of "ö", "ue" instead of "ü", and similar. All 6 German JSON files were generated with ASCII approximations instead of proper German characters. This plan does a complete pass through every German locale file and replaces every ASCII fallback with the correct Unicode character. Output: All 6 de/*.json files with proper German umlauts (ä, ö, ü, Ä, Ö, Ü, ß). @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/34-i18n-foundation/34-CONTEXT.md @.planning/phases/34-i18n-foundation/34-UAT.md Task 1: Replace ASCII fallbacks with proper umlauts in all 6 German locale files src/client/locales/de/common.json, src/client/locales/de/collection.json, src/client/locales/de/threads.json, src/client/locales/de/setups.json, src/client/locales/de/onboarding.json, src/client/locales/de/settings.json src/client/locales/de/common.json, src/client/locales/de/collection.json, src/client/locales/de/threads.json, src/client/locales/de/setups.json, src/client/locales/de/onboarding.json, src/client/locales/de/settings.json Read each German locale file fully. For every string value, replace ASCII umlaut approximations with proper Unicode characters. This is NOT a simple find-and-replace — you must check each word in context because "ae", "oe", "ue" are not always umlauts (e.g., "Israel" should not become "Israöl"). **Replacement rules (apply to German words only):** - `ae` → `ä` when it represents an umlaut (Loeschen → Löschen, Gegenstaende → Gegenstände, Waehrung → Währung, Aenderung → Änderung) - `oe` → `ö` when it represents an umlaut (Loeschen → Löschen, Groesse → Größe) - `ue` → `ü` when it represents an umlaut (Zurueck → Zurück, Ausruestung → Ausrüstung, Ueberpruefen → Überprüfen, Stueck → Stück, hinzufuegen → hinzufügen) - `Ae` → `Ä` at word start (Aenderung → Änderung) - `Oe` → `Ö` at word start - `Ue` → `Ü` at word start (Ueberpruefen → Überprüfen) - `ss` → `ß` where appropriate in German (Schliessen → Schließen, Groesse → Größe, Strasse → Straße, weiss → weiß) — but NOT in compounds like "Impressum" or "Pressemitteilung" **Known corrections (from UAT report and file inspection):** - `Loeschen` → `Löschen` - `Zurueck` → `Zurück` - `Bestaetigen` → `Bestätigen` - `Schliessen` → `Schließen` - `Gegenstaende` → `Gegenstände` - `Ausruestung` → `Ausrüstung` - `Waehrung` → `Währung` - `Schluessel` → `Schlüssel` - `hinzufuegen` → `hinzufügen` - `Hinzufuegen` → `Hinzufügen` - `Ueberpruefen` → `Überprüfen` - `verfuegbar` → `verfügbar` - `Stueck` → `Stück` - `Groesse` → `Größe` - `aendern` → `ändern` - `Aendern` → `Ändern` - `aehnlich` → `ähnlich` - `haeufig` → `häufig` - `unterstuetzen` → `unterstützen` - `Ernaehrung` → `Ernährung` - `Geraet` → `Gerät` - `Geraete` → `Geräte` - `gewuenscht` → `gewünscht` - `moeglich` → `möglich` - `moeglicherweise` → `möglicherweise` - `natuerlich` → `natürlich` - `pruefen` → `prüfen` - `Uebersicht` → `Übersicht` - `Veroeffentlichen` → `Veröffentlichen` - `oeffentlich` → `öffentlich` - `Oeffentlich` → `Öffentlich` - `wuenschen` → `wünschen` - `fuer` → `für` - `Fuer` → `Für` - `ueber` → `über` - `Ueber` → `Über` **Process for each file:** 1. Read the entire file 2. Go through every string value 3. Identify every German word that uses ASCII umlaut approximation 4. Replace with proper Unicode umlaut 5. Write the corrected file 6. Ensure the file is valid JSON after corrections **Also review for natural German phrasing.** While fixing umlauts, if you notice awkward or unnatural German translations, improve them. The goal (per D-14) is natural German, not word-for-word translation. **Do NOT change:** - JSON key names (only values) - Interpolation variables: {{count}}, {{name}}, etc. must remain exactly as-is - English loanwords used intentionally in German context (e.g., "Setup", "Thread", "Export", "Import", "CSV") cd /home/jlmak/Projects/jlmak/GearBox && echo "=== Checking for remaining ASCII fallbacks ===" && grep -r "Loeschen\|Zurueck\|Bestaetigen\|Schliessen\|Gegenstaende\|Ausruestung\|Waehrung\|Schluessel" src/client/locales/de/ && echo "FAIL: ASCII fallbacks still present" || echo "PASS: No known ASCII fallbacks found" && echo "=== Checking for proper umlauts ===" && grep -c "ä\|ö\|ü\|Ä\|Ö\|Ü\|ß" src/client/locales/de/common.json && echo "=== Key parity ===" && bun test tests/i18n/locales.test.ts 2>&1 | tail -5 All 6 German locale files use proper Unicode umlauts, no ASCII approximations remain, key parity test passes, German reads naturally ## Trust Boundaries | Boundary | Description | |----------|-------------| | locale JSON→i18n | Static bundled files — trusted, no runtime injection vector | ## STRIDE Threat Register | Threat ID | Category | Component | Disposition | Mitigation Plan | |-----------|----------|-----------|-------------|-----------------| | T-34-08 | Information Disclosure | de locale files | accept | Translation files contain only UI strings, no secrets. Same disposition as T-34-02 and T-34-06. | - `grep -r "Loeschen\|Zurueck\|Bestaetigen\|Schliessen" src/client/locales/de/` returns no matches - `grep -c "ä\|ö\|ü\|ß" src/client/locales/de/common.json` returns > 0 - All 6 de/*.json files are valid JSON - `bun test tests/i18n/locales.test.ts` passes (key parity maintained) - `bun run build` succeeds - Every German locale file uses proper Unicode umlauts (ä, ö, ü, Ä, Ö, Ü, ß) - Zero instances of known ASCII fallback patterns remain - German translations read naturally - Key parity test passes - Build passes After completion, create `.planning/phases/34-i18n-foundation/34-07-SUMMARY.md`