Translation-Keys – die App prüft ihre eigenen Texte
Datum: 2026-04-01
i18n bricht leise – bis der Nutzer es merkt
Ein Key fehlt in EN. Ein Twig-Template nutzt `translations.Foo.bar` statt `translations.FooBar.bar`. Ein Setter im Model heißt `footer_imprint`, die Vendor-Translation erwartet `footer_impressum`. Auf Deutsch sieht alles gut aus – der erste englische Besucher oder der Translation-Validator im CI sieht 500 oder leere Strings.
Agentic Engineering behandelt i18n als Quality-Gate – nicht als Freitags-Nacharbeit.
Das Problem
| Fehler | Wann sichtbar |
|---|---|
| Fehlender Key in einer Sprache | Sprachwechsel / Validator |
| Falscher ScreenKey in Twig | Runtime / 500 |
| Host-Model vs. Vendor-Keys | Translation-Validierung |
| Hardcodierter String im Template | SEO, Konsistenz, Review |
Manuelles Nachziehen nach jedem Feature skaliert nicht – vor allem nicht mit KI-generierten Screens.
Das Pattern: die Kette
Routing (routes-project-config.php + Vendor)
→ Screen-Script
→ Twig: translations.{ScreenKey}.{property}
→ translation/{lang}/screen-*/ oder projektspezifisch
→ UITemplateModel-Properties
Ein Subagent traversiert alle Screens aus dem gemergten Routing und vergleicht:
001. Keys in Translation-Dateien
002. Properties im Model (App oder fabian)
003. Referenzen in Twig
004. Parität DE/EN (und weitere Sprachen)
So sieht es bei uns aus
php start-vendor-subagent-ralph-loop.php subagent-check-translations
`subagent-check-translations`:
001. Lädt Routing wie `VendorRouteConfigLoaderService`.
002. Prüft jeden Screen (öffentlich + secure mit Autologin-Regeln).
003. Meldet fehlende Keys als FAILED – nicht „TODO“.
004. Läuft im Development-Workflow und nach größeren UI-Änderungen.
Naming-Konventionen
| Element | Konvention |
|---|---|
| Translation-Ordner | `screen-{name}` für Vendor-Screens |
| Twig-Zugriff | `translations.{ScreenKey}.seo_title` |
| Model | Properties in snake_case |
| Blog-Screen | `translation/{lang}/blog/{YYYYMMDD}-{slug}-{lang}.php` |
Vendor-Screens erwarten oft `ScreenUserLogin` als Key – Host-Templates mit `UserLogin` ohne Anpassung → Fehler.
Validator vs. menschliches Auge
Der `VendorTranslationValidationService` prüft, ob jeder Key in der Translation-Datei eine öffentliche Property im Model hat. Host-Models mit abweichenden Namen (z. B. nur `footer_imprint` statt `footer_impressum`) lösen 500 aus – bevor ein Nutzer klickt.
Lösung: Model an Vendor angleichen, Host-Translation entfernen (Vendor-Fallback), oder korrekte `screen-*` Pfade mit fabian-Models.
Anti-Patterns
001. Strings direkt in Twig – „nur ein Wort“ – wird zu 200 hardcodierten Texten.
002. Translation nur DE – EN vergisst man bis Production.
003. Alter Ordner `user-login` bei Vendor-Route `screen-user-login` – Falscher Pfad, falsches Model.
004. Dynamische Keys ohne Model-Property – Validator schlägt fehl.
005. i18n manuell „am Freitag“ – Wird nie grün im Ralph-Loop.
Integration im Workflow
| Trigger | Aktion |
|---|---|
| Neuer Screen | Translations DE+EN anlegen, dann `check-translations` |
| Template-Änderung | Keys in Briefing/Model nachziehen |
| Vendor-Update | `check-vendor-duplicates` + `check-translations` |
| Vor Push | Development-Workflow |
curl mit `?autologin=1` für secure Routes laut Projektregel – gleiche URLs wie der Subagent.
Häufige Fragen
Warum nicht nur Twig-Fehler abwarten?
Manche Fehler erst bei Validierung beim Request-Start – alle Screens zu curlen ist teuer; Routing-Traversal ist systematischer.
Muss jedes Wort übersetzt sein?
Ja für UI und SEO pro Screen – Base-Navigation in `base-{lang}.php`.
Blogposts?
Inhalt oft nur DE; SEO-Titel/-Description in `translation/.../blog/`.
Verwandte Beiträge
| Beitrag | Thema |
|---|---|
| Rules, Skills, Subagents | `@skill-translations` |
| Self-Testing | UI-Tests pro Screen |
| Briefing-First | Keys in Spec |
| check-screens | Twig + PHP zusammen |
Takeaway
i18n ist ein Quality-Gate im Workflow – kein Nachziehen am Freitag. Translation-Keys systematisch prüfen heißt: Routing → Twig → Model → alle Sprachen. Wer das dem Subagent überlässt, merkt Fehler vor dem Nutzer – und vor dem Commit.