# Ph4 — Deployment- und Test-Report (Multi-Language Feature) > Phase 4/4 des Dev-Orchestrator-Workflows für Issue **#71** (Epic). > Verantwortlich: Hermes (Implementierung) / Martin (Approval & Merge). > Stand: nach PR **#78** (offen, nicht gemerged). ## 1. Übersicht | Sub-Issue | Bereich | Commit | Status | | --------- | -------------------------------- | --------- | -------- | | #72 | Core (Locale, I18n, Tests) | `63c8c75` | ✅ | | #73 | LocaleController + Open-Redirect | `ce21242` | ✅ | | #74 | Locales + Layout | `4b1c779` | ✅ | | #75 | Locale-Switcher UI | `0186de9` | ✅ | | #76 | Accessibility (A11y) | `13a25ad` | ✅ | | #77 | Integration + E2E + Coverage | `a1984b9` | ✅ | | — | Cleanup: dead `app/controllers/` | `c5a608d` | ✅ | | **PR** | **#78 — i18n Epic** | — | 🟡 offen | ## 2. Architektur-Entscheidungen (ADR-002) - **Server-Side-Rendering (PHP)** — kein SPA, kein Static-Site. Begründung: SEO (``, `og:locale`, übersetzte ``), kein FOUC, günstiger als JSON-Payload. - **4 Sprachen** — DE (default, Quelle der Wahrheit) / EN-GB / UK / RU. - **Storage** — `app/Locales/{de,en,uk,ru}.php` als PHP-Arrays (kein JSON, keine DB). - **Resolution-Priorität** — `?lang=` > Cookie > `Accept-Language` > `de`-Fallback. - **A11y** — separate ARIA-Labels für `<main>` (`a11y.main`) und `<nav>` (`a11y.nav`), 44px Touch-Targets für Flaggen, `aria-current="true"` auf aktiver Sprache, per-field form errors mit `aria-invalid` + `aria-describedby`. - **Rechtliches** — Impressum/Datenschutz bleiben deutsch (§ 5 TMG/DSGVO), nur Navigation/Headings werden übersetzt. ## 3. Pre-Merge-Checkliste | Item | Status | | ----------------------------------------------------- | ------ | | Branch `feature/multilanguage-mvp` erstellt & gepusht | ✅ | | 7 Commits mit `closes #<sub-issue>` Messages | ✅ | | 140 PHPUnit-Tests, 2493 Assertions | ✅ | | I18n-Coverage 97% / Locale 100% (Ziel ≥85%) | ✅ | | E2E Flow (Playwright) für 4 Locales grün | ✅ | | Pre-Commit-Hooks + Safe-Commit-Script | ✅ | | Keine `print`/`echo` in Production-Code | ✅ | | Kein `sleep()` / keine Test-Order-Dependencies | ✅ | | ADR-002 in `docs/adr/` | ✅ | | Dead `app/controllers/` (lowercase) entfernt | ✅ | ## 4. Smoke-Test nach Merge (Test-Umgebung) Domain: `https://haus.test.kies-media.de` ### 4.1 Sprachauflösung | URL | Erwartet | | -------------------------------- | ------------- | | `/` (ohne Cookie) | Default DE | | `/?lang=en` | EN-GB Content | | `/?lang=uk` | UK Content | | `/?lang=ru` | RU Content | | `/?lang=fr` (ungültig) | Fallback DE | | Mit gesetztem `locale=en` Cookie | EN-GB Content | ### 4.2 Sichtprüfung pro Sprache - [ ] `<html lang="<code>">` korrekt - [ ] `<title>` übersetzt - [ ] Hero-Headlines übersetzt - [ ] Navigation-Labels übersetzt - [ ] Footer-aria-Label übersetzt - [ ] `og:locale` korrekt (de_DE / en_GB / uk_UA / ru_RU) - [ ] Locale-Switcher zeigt aktive Sprache mit `aria-current="true"` - [ ] Mind. ein `hreflang="<code>"`-Link pro Sprache im `<head>` ### 4.3 Funktionale Tests - [ ] Klick auf Flagge → URL `?lang=<code>` → Cookie gesetzt → Content gewechselt - [ ] Open-Redirect-Schutz: `?lang=en&redirect=https://evil.example` → Redirect bleibt auf eigener Domain - [ ] Form-Submit funktioniert in allen 4 Sprachen (deutsche Fehlermeldungen auf `/en`-Seite bleiben — gewollt, da Validation-Server-Side) - [ ] Mobile: Flaggen ≥44px Touch-Target, Hamburger-Nav funktioniert - [ ] Keyboard: Tab durch Switcher, Enter aktiviert, ESC schließt mobile Nav - [ ] Screen-Reader-Test (VoiceOver / NVDA): Locale-Switcher ankündigt aktive Sprache, Form-Fehler werden vorgelesen ### 4.4 Legal-Pages (DE-only) - [ ] `/impressum` und `/datenschutz` zeigen deutschen Textkörper - [ ] Navigation auf diesen Seiten ist übersetzt, Body nicht - [ ] `<html lang>` ist `de` auf diesen Seiten ## 5. Performance- und SEO-Checkliste - [ ] `view-source:` zeigt übersetzte Texte (kein `{{t()}}`-Placeholder) - [ ] Lighthouse-Score: Performance ≥90, SEO ≥95, A11y ≥95 - [ ] Keine Layout-Shifts beim Locale-Wechsel - [ ] `hreflang` Alternate-Links vollständig (`de`, `en-GB`, `uk`, `ru`) - [ ] `canonical`-Link zeigt auf kanonische URL (ohne `?lang=`) ## 6. Rollback-Strategie **Falls nach Deploy Probleme auftauchen:** 1. **Schnellster Rollback** — PR revert: ```bash git revert -m 1 <merge-commit> git push origin main ``` 2. **Selektiver Rollback** — einzelne Sub-Issue-Commits rückwärts: ```bash git revert c5a608d # cleanup git revert a1984b9 # F git revert 13a25ad # E git revert 0186de9 # D git revert 4b1c779 # C ``` 3. **Branch-only Rollback** — `main` zurücksetzen, Branch behalten für Hotfix: ```bash git checkout main git reset --hard <commit-vor-merge> git push --force-with-lease ``` 4. **Cookie-Cleanup** — falls User mit gesetztem `locale=en` auf alte Version zurückgehen, ist das harmlos (Cookie wird ignoriert). **Daten-Migration:** keine — Feature ist additiv (keine DB-Änderungen, keine Schema-Breaks). ## 7. Risiken & Annahmen - **Annahme:** Reines SSR reicht aus, kein Lazy-Loading pro Sprache nötig. - **Risiko:** Bestehende User ohne `locale`-Cookie sehen DE (gewollt). - **Risiko:** `Accept-Language: ru` von Bots könnte Page-Weight verfälschen — irrelevant für SEO, da `hreflang` Vorrang hat. - **Annahme:** Übersetzungen in `app/Locales/*.php` sind von Muttersprachlern reviewt. **Aktion:** Martin lässt DE-Original von UK/RU-Sprecher gegenlesen. ## 8. Post-Merge Follow-Ups (Backlog) - [ ] Übersetzungs-Review durch Muttersprachler - [ ] Analytics: Sprache als Custom-Dimension tracken - [ ] Lazy-Loading von Übersetzungen falls Bundle wächst (>50 KB) - [ ] `de.php` als TypeScript-Schema für Frontend-Vue (zukünftig) - [ ] CI-Workflow für Playwright E2E (statt manuell) ## 9. Sign-off | Rolle | Name | Datum | Freigabe | | --------------- | ------ | ---------- | ------------- | | Implementierung | Hermes | 2026-06-04 | ✅ | | Review & Merge | Martin | — | 🟡 ausstehend | **Merge-Freigabe:** Martin mit 'merge PR #78' (siehe gitea-dev-orchestrator Memory).