Add multilingual audit CI pipeline + extract mandelblog_content_guard
This commit is contained in:
58
mandelblog_content_guard/normalizers/de.py
Normal file
58
mandelblog_content_guard/normalizers/de.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
|
||||
DE_LINE_REPLACEMENTS = {
|
||||
"Häufig gestellte Fragen Transparent über Planung, Vorgehensweise und Management.": "Häufig gestellte Fragen Klarheit über Planung, Vorgehensweise und Management.",
|
||||
"Einführungsmeeting planen Projekte anzeigen Unverbindliches Gespräch, klares Angebot Wir entwickeln schnelle Websites und Webshops, die Ihr Team selbst pflegen kann.": "Erstgespräch planen · Projekte ansehen · Unverbindliches Gespräch mit klarem Angebot. Wir entwickeln schnelle Websites und Webshops, die Ihr Team selbst pflegen kann.",
|
||||
"Einführungsmeeting planen Dienstleistungen anzeigen Verbindlich und klar Wir entwickeln schnelle Websites und Webshops, die Ihr Team selbst pflegen kann.": "Erstgespräch planen · Dienstleistungen anzeigen · Unverbindliches Gespräch mit klarem Angebot. Wir entwickeln schnelle Websites und Webshops, die Ihr Team selbst pflegen kann.",
|
||||
"Steuern 0,00 € Korb ansehen Kasse Kontakt KONTAKT Lass uns dein Projekt konkret machen Einführungsmeeting planen Dienstleistungen anzeigen So können Sie Kontakt aufnehmen Wählen Sie die Route, die zu Ihrer Frage passt.": "Steuern 0,00 € Korb ansehen Kasse Kontakt KONTAKT Lassen Sie uns Ihr Projekt konkret machen Erstgespräch planen Dienstleistungen anzeigen So können Sie Kontakt aufnehmen Wählen Sie den Weg, der zu Ihrer Frage passt.",
|
||||
"Steuern 0,00 € Korb ansehen Kasse Starter Website PLAN Starter Website Plan Starter-Gespräch planen Alle Dienstleistungen anzeigen Was du bekommst Startseite + Kernseiten Professionelle Basis, die sofort Vertrauen schafft.": "Steuern 0,00 € Korb ansehen Kasse Starter-Website PLAN Starter-Website Starter-Gespräch planen Alle Dienstleistungen anzeigen Was Sie erhalten Startseite + Kernseiten Professionelle Basis, die sofort Vertrauen schafft.",
|
||||
"Steuern 0,00 € Korb ansehen Kasse Business Website PLAN Business Website Plan Beratungsgespräch planen Alle Dienstleistungen anzeigen Was du bekommst Detailliertes Seitenlayout Mehr Platz für Dienstleistungen, Fälle und Lead-Flows.": "Steuern 0,00 € Korb ansehen Kasse Business-Website PLAN Business-Website Beratungsgespräch planen Alle Dienstleistungen anzeigen Was Sie erhalten Detailliertes Seitenlayout Mehr Platz für Dienstleistungen, Referenzen und Lead-Flows.",
|
||||
}
|
||||
|
||||
DE_PHRASE_REPLACEMENTS = {
|
||||
"New": "Neu",
|
||||
"Einführungsmeeting": "Erstgespräch",
|
||||
"Intakegespräch": "Erstgespräch",
|
||||
"SEO-ready basis": "SEO-optimierte Basis",
|
||||
"Sales-ready mit skalierbarem Stack": "Verkaufsbereit mit skalierbarer Architektur",
|
||||
"Continuous Verbesserung": "Kontinuierliche Verbesserung",
|
||||
"Was du bekommst": "Was Sie erhalten",
|
||||
"Starter Website": "Starter-Website",
|
||||
"Business Website": "Business-Website",
|
||||
"Support & Wachstum": "Support & Wachstum",
|
||||
"Lass uns dein Projekt konkret machen": "Lassen Sie uns Ihr Projekt konkret machen",
|
||||
"Wählen Sie die Route, die zu Ihrer Frage passt.": "Wählen Sie den Weg, der zu Ihrer Frage passt.",
|
||||
"Verbindlich und klar": "Unverbindliches Gespräch mit klarem Angebot",
|
||||
"Unverbindliches Gespräch, klares Angebot": "Unverbindliches Gespräch mit klarem Angebot",
|
||||
}
|
||||
|
||||
|
||||
def _apply_boundary_replacements(text: str, replacements: dict[str, str]) -> str:
|
||||
cleaned = text
|
||||
phrase_replacements = {}
|
||||
token_replacements = {}
|
||||
for source, target in replacements.items():
|
||||
if re.fullmatch(r"[\wÀ-ÿ-]+", source, flags=re.UNICODE):
|
||||
token_replacements[source] = target
|
||||
else:
|
||||
phrase_replacements[source] = target
|
||||
|
||||
for source, target in sorted(phrase_replacements.items(), key=lambda item: len(item[0]), reverse=True):
|
||||
cleaned = cleaned.replace(source, target)
|
||||
|
||||
for source, target in sorted(token_replacements.items(), key=lambda item: len(item[0]), reverse=True):
|
||||
pattern = re.compile(rf"(?<![\wÀ-ÿ-]){re.escape(source)}(?![\wÀ-ÿ-])", re.UNICODE)
|
||||
cleaned = pattern.sub(target, cleaned)
|
||||
return cleaned
|
||||
|
||||
|
||||
def normalize_de_text(text: str, field_path: str = "") -> str:
|
||||
cleaned = text
|
||||
for source, target in DE_LINE_REPLACEMENTS.items():
|
||||
if cleaned == source:
|
||||
return target
|
||||
cleaned = _apply_boundary_replacements(cleaned, DE_PHRASE_REPLACEMENTS)
|
||||
return cleaned
|
||||
Reference in New Issue
Block a user