Files
schalli bf7f250c81
Tessera CI/CD / Lint & Type Check (push) Successful in 44s
Tessera CI/CD / Tests (push) Successful in 49s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m51s
docs(quick-260907-hyi): Abnahme dokumentiert, Umlaut-Korrektur abgeschlossen
Die Browser-Abnahme hat drei uebersehene Stellen gefunden — "Aenderungen speichern",
"Oeffnen" und einen LDAP-Hinweis — und damit die Luecke im Waechter aufgedeckt, durch
die sie geschluepft sind: sein Verdachtsmuster war case-sensitiv. Beides mit 85d2d77
behoben.

In der SUMMARY festgehalten, wie geprueft wurde: eine unabhaengige Analyse aller
Tokens in de.json findet keine Ersatzschreibung mehr, der Schluesselsatz ist
unveraendert bei 787, und die Modulbeschreibung in der bestehenden Datenbank ist beim
API-Neustart per Seed-Upsert mitgewandert — ohne Migration, wie geplant.

Ausserdem vermerkt, dass eine erste Sichtpruefung per fetch aus der laufenden Seite
faelschlich Entwarnung gab. Dieselbe Methode hatte in dieser Sitzung schon einmal ein
falsches Ergebnis geliefert; die berichteten Zahlen stammen aus echten
Seitenaufrufen.

Backlog-Punkt zu den Umlauten nach completed verschoben.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K5jtbGzC5Sf9npJ3JCjKhq
2026-09-07 13:20:36 +02:00

183 lines
9.3 KiB
Markdown

---
quick_id: 260907-hyi
title: Umlaute in der deutschen Oberflaeche korrigieren
status: complete
tech-stack:
patterns:
- "Explizite Ersetzungs-/Positivliste statt Zeichenregel fuer Umlaut-Korrektur"
key-files:
created:
- apps/web/src/messages/umlaut-dictionary.ts
- apps/web/src/messages/umlaut-guard.spec.ts
modified:
- apps/web/src/messages/de.json
- apps/api/src/mail/mail.service.ts
- apps/api/src/domaincheck/domaincheck.seed.ts
decisions:
- "ss/ß-Faelle (Groesse, Schliessen, ausschliessen, Gruessen) wurden mitkorrigiert statt ausgeklammert, da derselbe Defekt."
- "Fehlende Woerterbuch-Eintraege, die der neue Waechter selbst aufdeckte, wurden inline nachgezogen (Rule 1 - Bug)."
actuals:
tokens: 9975
tasks: 3
commits: 3
plan_head_before: bec0530a2b2638b47fbc91dc9017cda148f5c37f
metrics:
duration: "~25 min"
completed: 2026-09-07
---
# Quick-Task 260907-hyi: Umlaute in der deutschen Oberflaeche korrigieren Summary
Deutsche Oberflaechentexte, Passwort-/Willkommens-Mail und Marktplatz-Modulbeschreibung
schrieben Umlaute als Buchstabenpaare aus; jetzt schreiben sie echte Umlaute, per expliziter
Token-Liste korrigiert und mit einem Vitest-Waechter gegen Rueckfall abgesichert.
## Ausgefuehrte Tasks
1. **Woerterbuch anlegen und de.json korrigieren** — `umlaut-dictionary.ts` angelegt
(`UMLAUT_REPLACEMENTS`, `UMLAUT_ALLOWLIST`), 68 falsche Tokens (140 Fundstellen inkl. der
in Task 2 entdeckten Ergaenzung) in `de.json` per Ganzwort-Ersetzung korrigiert. Commit
`3d351c6`.
2. **Regressionswaechter als Vitest-Spec** — `umlaut-guard.spec.ts` angelegt, liest
ausschliesslich das geparste JSON, prueft drei Dinge (keine bekannten Ersatzschreibweisen
mehr, kein neues ae/oe/ue/ss-Token ausserhalb der Positivliste, de/en-Schluesselparitaet).
Commit `caa4827`.
3. **API-Texte — Passwort-Mail und Modul-Beschreibung** — `mail.service.ts` (Betreff,
Reset-Fliesstext, Willkommens-Mail) und `domaincheck.seed.ts` korrigiert. Commit `d9f1422`.
4. **Sichtpruefung im Browser und in der Datenbank** — `checkpoint:human-verify`, absichtlich
nicht ausgefuehrt. Der Orchestrator fuehrt Docker-Rebuild und die visuelle Pruefung durch.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Bug] Fehlender Grossschreibungs-Eintrag `Bestaetigen` → `Bestätigen`**
- **Found during:** Task 2, beim ersten Lauf des neuen Waechters.
- **Issue:** Die Plan-Wortliste fuehrte nur `bestaetigen→bestätigen` (klein), aber
`common.confirm` in `de.json` nutzt die Grossschreibung `"Bestaetigen"` (Schaltflaechen-Text)
— blieb nach Task 1 faelschlich unkorrigiert.
- **Fix:** `Bestaetigen: 'Bestätigen'` zu `UMLAUT_REPLACEMENTS` ergaenzt, `de.json`-Wert
direkt korrigiert.
- **Files modified:** `apps/web/src/messages/umlaut-dictionary.ts`, `apps/web/src/messages/de.json`
- **Commit:** `caa4827`
**2. [Rule 1 - Bug] Fehlende Positivlisten-Eintraege fuer nach der Korrektur entstandene, aber weiterhin ae/oe/ue/ss-haltige korrekte Woerter**
- **Found during:** Task 2, gleicher Waechter-Lauf.
- **Issue:** Die Korrektur von `Passwoerter`, `vertrauenswuerdigen`, `ausschliessen`,
`entschluesselt` ergibt korrektes Deutsch (`Passwörter`, `vertrauenswürdigen`,
`ausschließen`, `entschlüsselt`), das aber weiterhin die Zeichenfolge `ss`/`ue` enthaelt
(z. B. `üssel`, `au` + `e` in `trauen`, `uss` in `ausschließen`) und deshalb vom
zweiten Waechter-Test als "neues Wort" markiert wurde.
- **Fix:** Die vier Woerter zu `UMLAUT_ALLOWLIST` ergaenzt.
- **Files modified:** `apps/web/src/messages/umlaut-dictionary.ts`
- **Commit:** `caa4827`
Beide Punkte wurden inline behoben, nicht als separate Commits — sie sind Teil der
Fertigstellung des in Task 1/2 beschriebenen Woerterbuchs, keine architektonische Aenderung.
## Test-/Build-Ergebnisse (real, nicht simuliert)
- `pnpm --filter @tessera/web test`: **38 Testdateien, 225 Tests — alle gruen** (inkl. neuem
`umlaut-guard.spec.ts` und bestehender `tenderRadar-parity.spec.ts`).
- `pnpm --filter @tessera/web run type-check`: sauber, keine Ausgabe.
- `pnpm --filter @tessera/api run build`: sauber, keine Ausgabe.
- `pnpm --filter @tessera/api run type-check`: sauber, keine Ausgabe.
- `pnpm --filter @tessera/api run test`: **46 Testdateien, 642 Tests — alle gruen** (mehrere
erwartete `ERROR`/`WARN`-Log-Zeilen in der Ausgabe stammen von absichtlich simulierten
Fehlerpfaden in bestehenden Tests, kein neuer Testfehler).
- Manuelle Waechter-Probe (Task 2 `done`-Kriterium): ein probeweise eingefuegtes `fuer`
liess die Spec mit exakt der geforderten Meldung fehlschlagen (`"für"` + Schluesselpfad
`common.edit`), danach zurueckgenommen — `git diff --stat` bestaetigt keine Restspur.
## Wieviele Strings geaendert wurden
- **68 verschiedene Tokens** in `UMLAUT_REPLACEMENTS` (67 aus dem Plan + 1 selbst gefunden:
`Bestaetigen`), **140 Ersetzungs-Treffer** in `de.json`-Werten insgesamt.
- **65 Tokens** auf `UMLAUT_ALLOWLIST` (61 aus dem Plan + 4 selbst ergaenzt).
- **6 Zeichenketten** in `apps/api/src/mail/mail.service.ts` (Betreff + 5 Fliesstext-/
Template-Literal-Stellen in beiden Mails).
- **1 Zeichenkette** in `apps/api/src/domaincheck/domaincheck.seed.ts`.
## Was bewusst unangetastet blieb
- `empfaenger@example.com` (Schluessel `testToPlaceholder`) — Platzhalter-Adresse, per
`@`-Regel uebersprungen, wie im Plan gefordert.
- Alle 65 Positivlisten-Woerter (`Passwort`, `Adresse`, `Quelle`, `manuell`, `Ausschreibung`,
`Erzeugnisse`, `zuerst`, `neue`, ...) — unveraendert, keine einzige Ersetzung darauf
angewendet.
- Deutsche Code-Kommentare (z. B. in `tessera-logo.tsx`) — laut Plan ausdruecklich nicht
Teil dieses Tasks, nicht angefasst.
- Wortlaut jeder Zeichenkette — nur Schreibweise korrigiert, keine Umformulierung.
- Schluessel und Reihenfolge in `de.json`/`en.json` — strukturell identisch geblieben (787
Schluessel, geprueft per Skript vor und nach der Aenderung).
- Die beiden Backlog-Punkte aus dem Plan (`1 Mitglieder` statt `1 Mitglied`; Duzen im
Aktivierungsdialog) — ausdruecklich nicht Teil dieses Plans, bereits im Backlog unter
`.planning/phases/15-modul-berechtigungen-gruppen-user-grants/15-UAT-2026-09-07.md` vermerkt.
- Task 4 (Sichtpruefung, Docker-Rebuild) — `checkpoint:human-verify`, dem Orchestrator
ueberlassen.
## Self-Check: PASSED
- `apps/web/src/messages/umlaut-dictionary.ts` — FOUND
- `apps/web/src/messages/umlaut-guard.spec.ts` — FOUND
- Commit `3d351c6` — FOUND (`git log --oneline --all`)
- Commit `caa4827` — FOUND
- Commit `d9f1422` — FOUND
## Task 4 — Abnahme am 2026-09-07, mit Nachbesserung
Der Orchestrator hat Web und API neu gebaut und die Oberflaeche im Browser geprueft.
Die Abnahme hat **drei uebersehene Stellen** gefunden, darunter zwei gut sichtbare
Schaltflaechen:
| falsch | richtig | Ort |
|---|---|---|
| `Aenderungen speichern` | Änderungen speichern | Dashboard-Bearbeitungsleiste |
| `Oeffnen` | Öffnen | Modul oeffnen |
| `Eine Aenderung ist hier nicht moeglich` | Eine Änderung … | LDAP-Hinweis im Konto |
### Warum der Waechter sie durchgelassen hat
Sein Verdachtsmuster war `/(ae|oe|ue|ss)/` — **case-sensitiv**. "Aenderungen" beginnt
mit "Ae", nicht mit "ae", und konnte deshalb gar nicht anschlagen. Derselbe Fehler
war auch in der ersten Analyse des Orchestrators und hat dort zunaechst zu einem
falschen Entwarnungssignal gefuehrt.
Behoben in Commit `85d2d77`:
- Muster auf `/(ae|oe|ue|ss)/i` umgestellt — erfasst jetzt auch grossgeschriebene
Formen.
- `Aenderung`, `Aenderungen`, `Oeffnen` ins Woerterbuch aufgenommen und in `de.json`
korrigiert (4 Fundstellen).
- Durch die schaerfere Pruefung melden sich neu die Abkuerzungen `RSS`,
`RSSGenerator` und `SSL`. Sie tragen ein doppeltes S ohne Umlaut-Bezug und stehen
jetzt auf der Positivliste.
### Zwei weitere Nutzertexte, die der erste Durchgang nicht als solche erkannt hatte
`ldap.service.ts` schreibt zwei Meldungen in `result.errors`. Das ist kein Protokoll,
sondern die Fehlerliste, die dem Administrator auf der LDAP-Seite angezeigt wird
(`admin/ldap/page.tsx:1028`). Beide korrigiert: "ungueltiger ldapObjectGuid-Wert" und
"Base-DN-Konfiguration pruefen. Nicht geloescht." Drei Tests pinnen diese Texte
bewusst und wurden mitgezogen.
**Bewusst nicht angefasst:** die Warnung in `crypto.service.ts`. Sie geht ueber
`logger.warn` ins Protokoll und nicht an einen Nutzer.
### Gegenproben
| Pruefung | Ergebnis |
|---|---|
| Unabhaengige Analyse aller Tokens in `de.json` mit ae/oe/ue | keine Ersatzschreibung mehr; die 26 verbleibenden Treffer sind korrektes Deutsch (Quelle, manuell, Aktuell, neue, dauerhaft …) |
| Schluesselsatz de/en | 787 / 787, identisch |
| Modulbeschreibung in der **bestehenden** Datenbank nach API-Neustart | `Domain-Verfügbarkeit prüfen` — der Seed-Upsert hat die Altzeile mitgezogen, ohne Migration |
| Browser, echte Navigation | "Änderungen speichern", "Widget hinzufügen", "hinzuzufügen", "Verfügbar", "Domain-Verfügbarkeit prüfen" korrekt |
| Testlaeufe | 642 API-Tests, 225 Web-Tests, beide Typpruefungen gruen |
### Nachtrag zur Belastbarkeit der Messmethode
Eine erste Sichtpruefung per `fetch()` aus der laufenden Seite heraus meldete alle
Seiten als sauber. Dieselbe Methode hatte in dieser Sitzung schon einmal ein falsches
Ergebnis geliefert, weil sie die Sitzung nicht wie eine echte Navigation mitfuehrt.
Die oben berichteten Ergebnisse stammen deshalb aus echten Seitenaufrufen.