Files
tessera-ctl/apps/web/src/messages/umlaut-dictionary.ts
T
schalli d63d9f5563 feat(quick-260921-qd3): XFrame-Widget - Webseite als Rahmen im Dashboard, Sandbox ohne Top-Navigation, Neuladen-Intervall
- xframe-config.ts: Resolver (https-Pruefung via isHttpsUrl des Bilderrahmens,
  Titel bis 100 Zeichen, Neuladen 0/60/300/600/1800/3600 s geklemmt),
  XFRAME_SANDBOX ohne allow-top-navigation und allow-modals; 12 Tests zuerst rot
- xframe-widget.tsx: genau ein <iframe> (sandbox, allow="", no-referrer, lazy),
  Kopfleiste mit Titel oder Ecksymbol "In neuem Tab oeffnen", Neuladen ueber
  key-Wechsel mit Timer-Raeumung, transparente Flaeche im Bearbeitungsmodus
  damit die Kachel Ziehgriff bleibt; 12 Tests zuerst rot
- xframe-config-form.tsx: Adresse/Titel mit Uebernahme bei Blur/Enter, http wird
  mit Meldung abgewiesen und nicht gespeichert, Intervall-Auswahl, dauerhafter
  Hinweis auf verweigertes Einbetten; 8 Tests
- Panel-Zweig samt "— Titel" in der Kopfzeile, Registry (12x12, Fenster-Symbol),
  Katalog, Seite, DTO @IsIn, de/en widgets.xframe (15 Schluessel), Umlaut-Allowlist
  "neuem"; der Server ruft die Adresse nie ab

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 19:18:48 +02:00

186 lines
5.2 KiB
TypeScript

/**
* umlaut-dictionary — single source of truth for the ae/oe/ue/ss umlaut
* correction in `de.json` and for the `umlaut-guard.spec.ts` regression
* guard.
*
* Why an explicit token list instead of a character rule (`ue` -> `ü`,
* `oe` -> `ö`, `ae` -> `ä`): a blanket character substitution destroys
* correct German. `Quelle` would become `Qülle`, `manuell` would become
* `manüll`, `neuen` would become `nün`, `Erzeugnisse` would become
* `Erzügnisse`. Replacement therefore only ever targets a whole token
* that is an exact key in `UMLAUT_REPLACEMENTS`.
*
* `UMLAUT_ALLOWLIST` lists every token that legitimately contains
* `ae`/`oe`/`ue`/`ss` and is already correct German — it must never be
* replaced. `empfaenger` sits on this list purely because it is part of
* the example placeholder address `empfaenger@example.com`
* (key `testToPlaceholder`): an umlaut inside a placeholder email address
* would wrongly suggest umlaut addresses are the expected format, so that
* value is skipped entirely (any string containing `@`) rather than
* "corrected".
*/
/** Wrong substitute spelling -> correct German spelling, exact token match only. */
export const UMLAUT_REPLACEMENTS: Record<string, string> = {
loeschen: 'löschen',
Loeschen: 'Löschen',
geloescht: 'gelöscht',
hinzufuegen: 'hinzufügen',
Hinzufuegen: 'Hinzufügen',
hinzuzufuegen: 'hinzuzufügen',
einfuegen: 'einfügen',
fuege: 'füge',
Fuege: 'Füge',
Fuegen: 'Fügen',
fuer: 'für',
pruefen: 'prüfen',
Pruefen: 'Prüfen',
Pruefe: 'Prüfe',
Pruefung: 'Prüfung',
geprueft: 'geprüft',
ueberpruefen: 'überprüfen',
Ueberpruefe: 'Überprüfe',
Zertifikatspruefung: 'Zertifikatsprüfung',
aendern: 'ändern',
// Nachtrag 2026-09-07: die grossgeschriebenen Formen fehlten. Der Waechter
// hat sie nicht gemeldet, weil sein Verdachtsmuster case-sensitiv war und
// "Ae"/"Oe" deshalb durchrutschten — mitbehoben in umlaut-guard.spec.ts.
Aenderung: 'Änderung',
Aenderungen: 'Änderungen',
Oeffnen: 'Öffnen',
geaendert: 'geändert',
Moechten: 'Möchten',
moeglich: 'möglich',
moegliche: 'mögliche',
koennen: 'können',
verfuegbar: 'verfügbar',
Verfuegbar: 'Verfügbar',
Verfuegbare: 'Verfügbare',
Verfuegbarkeit: 'Verfügbarkeit',
Zurueck: 'Zurück',
Zuruecksetzen: 'Zurücksetzen',
zuruecksetzen: 'zurücksetzen',
zurueckgesetzt: 'zurückgesetzt',
rueckgaengig: 'rückgängig',
Zusammenfuehren: 'Zusammenführen',
zusammenfuehren: 'zusammenführen',
bestaetigen: 'bestätigen',
Bestaetigen: 'Bestätigen',
Passwoerter: 'Passwörter',
spaeter: 'später',
ueberein: 'überein',
uebersprungen: 'übersprungen',
ueber: 'über',
ungueltig: 'ungültig',
Verschluesselung: 'Verschlüsselung',
entschluesselt: 'entschlüsselt',
ausgewaehlt: 'ausgewählt',
Ausgewaehlt: 'Ausgewählt',
ausgewaehlte: 'ausgewählte',
Ausgewaehlte: 'Ausgewählte',
waehle: 'wähle',
benoetigt: 'benötigt',
noetig: 'nötig',
muessen: 'müssen',
Domaene: 'Domäne',
Einschraenkung: 'Einschränkung',
Empfaenger: 'Empfänger',
Oberflaeche: 'Oberfläche',
Postfaecher: 'Postfächer',
Praefix: 'Präfix',
Sicherheitsgruenden: 'Sicherheitsgründen',
unterstuetzt: 'unterstützt',
vertrauenswuerdigen: 'vertrauenswürdigen',
zusaetzlich: 'zusätzlich',
zusaetzliche: 'zusätzliche',
Groesse: 'Größe',
Schliessen: 'Schließen',
ausschliessen: 'ausschließen',
};
/**
* Tokens containing `ae`/`oe`/`ue`/`ss` that are already correct German
* and must never be touched by the replacement or flagged by the guard.
*/
export const UMLAUT_ALLOWLIST: readonly string[] = [
'manuell',
'Manuell',
'Quelle',
'Quellen',
'Quell',
'Quellportal',
'Kalenderquelle',
'Kalenderquellen',
'Energiequellen',
'neue',
'neuen',
'neuere',
'Neue',
'Neues',
'aktuelle',
'Aktuell',
'Aktuelle',
'Aktuelles',
'zuerst',
'dauerhaft',
'Schauen',
'Taktfrequenz',
'Feuerlösch',
'Bergbauerzeugnisse',
'true',
'guest',
'Passwort',
'Adresse',
// Bilderrahmen-Widget (quick-260921-pi9): korrektes Deutsch mit „ss“
'Webadresse',
'Bildausschnitt',
// XFrame-Widget (quick-260921-qd3): „In neuem Tab öffnen“, korrektes Deutsch wie neuen
'neuem',
'Absenderadresse',
'muss',
'musste',
'müssen',
'lassen',
'vergessen',
'stattdessen',
'Wasser',
'Abwasser',
'Hessen',
'Erzeugnisse',
'Druckerzeugnisse',
'Gummierzeugnisse',
'Mineralölerzeugnisse',
'Ausschreibung',
'Ausschreibungen',
'Ausschreibungs',
'Ausschreibungsdetails',
'erfasst',
'erfasster',
'Erfassung',
'Ergebnisse',
'gedrosselt',
'ausgeschlossen',
'Ausgeschlossen',
'Ausschlussliste',
'Informationssysteme',
'Zeitmessung',
'Tessera',
'Passen',
'Passt',
'Fasst',
'Verschlüsselung',
'empfaenger',
'Passwörter',
'vertrauenswürdigen',
'ausschließen',
'entschlüsselt',
// Nachtrag 2026-09-07: Abkuerzungen mit doppeltem S. Sie tauchen erst auf,
// seit das Verdachtsmuster case-insensitiv prueft — vorher fiel jedes
// grossgeschriebene "SS" durch dasselbe Loch wie "Aenderungen".
'RSS',
'RSSGenerator',
'SSL',
// 260914-m97: Fehler-melden-Knopf, Pflichtlabel "Was ist passiert?"
'passiert',
];