# 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 (`<html lang>`, `og:locale`, übersetzte `<title>`), 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).
