Immobilien site 11-05-2026
This commit is contained in:
parent
e198d842ce
commit
6799325f71
28 changed files with 16189 additions and 809 deletions
226
dev/immobilien 07-05-2026/fix-umlauts.php
Normal file
226
dev/immobilien 07-05-2026/fix-umlauts.php
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Convert ae/oe/ue/ss in German fields to proper umlauts (ä/ö/ü/ß).
|
||||
*
|
||||
* Strategy:
|
||||
* - Keep English/quote fields untouched (`official_*`, `slug`, `image`, urls).
|
||||
* - Use a curated word-level mapping so we never change English loanwords
|
||||
* (Avenue, Asset, Business, Boutique, Resale, ...).
|
||||
* - Apply replacements to every German string field (recursive walk).
|
||||
*/
|
||||
$file = __DIR__.'/../../resources/lang/de/immobilien-azizi.json';
|
||||
$json = json_decode(file_get_contents($file), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
/**
|
||||
* Keys whose string values must NOT be touched. Includes Azizi-source quotes
|
||||
* and structural fields.
|
||||
*/
|
||||
$skipKeys = [
|
||||
'official_headline',
|
||||
'official_description',
|
||||
'official_unit_type',
|
||||
'official_starting_price',
|
||||
'official_url',
|
||||
'slug',
|
||||
'image',
|
||||
'category',
|
||||
'status_group',
|
||||
'data_confidence',
|
||||
'overview_bedrooms',
|
||||
'key',
|
||||
];
|
||||
|
||||
/**
|
||||
* Word-level replacements. Order matters: longer words first so we don't
|
||||
* partially match a shorter sibling.
|
||||
*
|
||||
* Each replacement replaces the *entire word* via word-boundary regex.
|
||||
*/
|
||||
$wordMap = [
|
||||
// ae / Ae
|
||||
'Bauchgefuehl' => 'Bauchgefühl',
|
||||
'Bestandskaeufer' => 'Bestandskäufer',
|
||||
'Datensaetze' => 'Datensätze',
|
||||
'Einschaetzung' => 'Einschätzung',
|
||||
'Ergaenzt' => 'Ergänzt',
|
||||
'Ergaenzung' => 'Ergänzung',
|
||||
'Erstkaeufer' => 'Erstkäufer',
|
||||
'Erzaehlung' => 'Erzählung',
|
||||
'Europaeisch' => 'Europäisch',
|
||||
'europaeisch' => 'europäisch',
|
||||
'Flaechenbedarf' => 'Flächenbedarf',
|
||||
'Flaechenzuschnitte' => 'Flächenzuschnitte',
|
||||
'Gebaeude' => 'Gebäude',
|
||||
'Gebaeuden' => 'Gebäuden',
|
||||
'Gebaeudehoehe' => 'Gebäudehöhe',
|
||||
'Kaeufen' => 'Käufen',
|
||||
'Kaeufer' => 'Käufer',
|
||||
'Kaeufern' => 'Käufern',
|
||||
'Naehe' => 'Nähe',
|
||||
'Praeferenz' => 'Präferenz',
|
||||
'Projektqualitaet' => 'Projektqualität',
|
||||
'Renditekaeufer' => 'Renditekäufer',
|
||||
'Vergleichsadresse' => 'Vergleichsadresse', // unchanged (no umlaut needed)
|
||||
'Vermietungskaeufer' => 'Vermietungskäufer',
|
||||
'bewaehrten' => 'bewährten',
|
||||
'ergaenzen' => 'ergänzen',
|
||||
'ergaenzt' => 'ergänzt',
|
||||
'zusaetzlich' => 'zusätzlich',
|
||||
'Projektuebersicht' => 'Projektübersicht',
|
||||
'Waehrungslogik' => 'Währungslogik',
|
||||
'Zentralitaetskaeufer' => 'Zentralitätskäufer',
|
||||
'abhaengig' => 'abhängig',
|
||||
'erklaert' => 'erklärt',
|
||||
'faellt' => 'fällt',
|
||||
'klaeren' => 'klären',
|
||||
'laeuft' => 'läuft',
|
||||
'naechsten' => 'nächsten',
|
||||
'spaeter' => 'später',
|
||||
'spaetere' => 'spätere',
|
||||
'waehrend' => 'während',
|
||||
'zaehlen' => 'zählen',
|
||||
'zaehlt' => 'zählt',
|
||||
// ae mid-word (compound and case variants)
|
||||
'Exklusivitaet' => 'Exklusivität',
|
||||
'Liquiditaet' => 'Liquidität',
|
||||
'Vermietungsstaerke' => 'Vermietungsstärke',
|
||||
'Staerke' => 'Stärke',
|
||||
'Wohnflaeche' => 'Wohnfläche',
|
||||
'Wohnflaechensegment' => 'Wohnflächensegment',
|
||||
'groessenstaerkere' => 'größenstärkere',
|
||||
|
||||
// ue / Ue
|
||||
'Frueher' => 'Früher',
|
||||
'frueh' => 'früh',
|
||||
'fruehe' => 'frühe',
|
||||
'Fuenf' => 'Fünf',
|
||||
'Fuer' => 'Für',
|
||||
'fuer' => 'für',
|
||||
'Gruenflaechen' => 'Grünflächen',
|
||||
'Kuechen' => 'Küchen',
|
||||
'Kuerzlich' => 'Kürzlich',
|
||||
'Masterplaene' => 'Masterpläne',
|
||||
'Moebel' => 'Möbel',
|
||||
'Persoenlich' => 'Persönlich',
|
||||
'Persoenliche' => 'Persönliche',
|
||||
'Suedwestlicher' => 'Südwestlicher',
|
||||
'Tuerme' => 'Türme',
|
||||
'Verfuegbar' => 'Verfügbar',
|
||||
'Verfuegbarkeit' => 'Verfügbarkeit',
|
||||
'Verfuegbarkeitspruefung' => 'Verfügbarkeitsprüfung',
|
||||
'Vergleichsmoeglichkeiten' => 'Vergleichsmöglichkeiten',
|
||||
'Wohnungsgroessen' => 'Wohnungsgrößen',
|
||||
'Investmentgroessen' => 'Investmentgrößen',
|
||||
'Zahlungsschritte' => 'Zahlungsschritte', // unchanged
|
||||
'Zusaetzliche' => 'Zusätzliche',
|
||||
'dafuer' => 'dafür',
|
||||
'eroeffnen' => 'eröffnen',
|
||||
'fuehrt' => 'führt',
|
||||
'gegenueber' => 'gegenüber',
|
||||
'gehoert' => 'gehört',
|
||||
'geprueft' => 'geprüft',
|
||||
'grossen' => 'großen',
|
||||
'grosses' => 'großes',
|
||||
'grosse' => 'große',
|
||||
'Grosses' => 'Großes',
|
||||
'Grosse' => 'Große',
|
||||
'grosszuegigen' => 'großzügigen',
|
||||
'hoeherem' => 'höherem',
|
||||
'hoeheres' => 'höheres',
|
||||
'hoeherwertiger' => 'höherwertiger',
|
||||
'juenger' => 'jünger',
|
||||
'juengere' => 'jüngere',
|
||||
'juengeren' => 'jüngeren',
|
||||
'juengste' => 'jüngste',
|
||||
'koennen' => 'können',
|
||||
'kuenstlichem' => 'künstlichem',
|
||||
'kuenstlicher' => 'künstlicher',
|
||||
'muessen' => 'müssen',
|
||||
'nuetzlich' => 'nützlich',
|
||||
'oestlichen' => 'östlichen',
|
||||
'oestlicher' => 'östlicher',
|
||||
'persoenlich' => 'persönlich',
|
||||
'persoenliche' => 'persönliche',
|
||||
'pruefe' => 'prüfe',
|
||||
'pruefen' => 'prüfen',
|
||||
'schoenste' => 'schönste',
|
||||
'stoeckiges' => 'stöckiges',
|
||||
'suedwestliche' => 'südwestliche',
|
||||
'suedwestlicher' => 'südwestlicher',
|
||||
'ueber' => 'über',
|
||||
'Ueber' => 'Über',
|
||||
'uebergeben' => 'übergeben',
|
||||
'ueberschaubar' => 'überschaubar',
|
||||
'ueberzeugend' => 'überzeugend',
|
||||
'ueberzeugt' => 'überzeugt',
|
||||
'ueblicherweise' => 'üblicherweise',
|
||||
'ungewoehnlichem' => 'ungewöhnlichem',
|
||||
'urspruengliche' => 'ursprüngliche',
|
||||
'verfuegbar' => 'verfügbar',
|
||||
'wasserorientiertes' => 'wasserorientiertes', // unchanged
|
||||
'zeitgenoessischer' => 'zeitgenössischer',
|
||||
'zuegig' => 'zügig',
|
||||
'zugaenglicher' => 'zugänglicher',
|
||||
'zugaenglichsten' => 'zugänglichsten',
|
||||
|
||||
// oe / Oe (mostly already covered above; keep explicit ones too)
|
||||
'franzoesisch' => 'französisch',
|
||||
'umweltbewusst' => 'umweltbewusst', // unchanged
|
||||
'Erdgeschoss' => 'Erdgeschoss', // unchanged - no ß
|
||||
|
||||
// ss → ß (only true ß-words; loanwords like Adresse, Prozess stay)
|
||||
'Groesse' => 'Größe',
|
||||
'groesste' => 'größte',
|
||||
'groessten' => 'größten',
|
||||
'groessere' => 'größere',
|
||||
'Groesserer' => 'Größerer',
|
||||
'groesseres' => 'größeres',
|
||||
'Grossanlage' => 'Großanlage',
|
||||
'Grossentwicklung' => 'Großentwicklung',
|
||||
'grundsaetzlich' => 'grundsätzlich',
|
||||
'Strassenanbindung' => 'Straßenanbindung',
|
||||
'Einkaufsstrassen' => 'Einkaufsstraßen',
|
||||
'einfliessen' => 'einfließen',
|
||||
];
|
||||
|
||||
/**
|
||||
* Build regex once: \b(WORD1|WORD2|...)\b with case-sensitive matching.
|
||||
*/
|
||||
$keys = array_keys($wordMap);
|
||||
usort($keys, fn ($a, $b) => strlen($b) <=> strlen($a)); // longest first
|
||||
$pattern = '/\b('.implode('|', array_map('preg_quote', $keys)).')\b/u';
|
||||
|
||||
$replacements = 0;
|
||||
$walk = function (&$node, $parentKey = null) use (&$walk, $skipKeys, $wordMap, $pattern, &$replacements) {
|
||||
if (is_array($node)) {
|
||||
foreach ($node as $k => &$v) {
|
||||
if (is_string($k) && in_array($k, $skipKeys, true)) {
|
||||
continue;
|
||||
}
|
||||
$walk($v, $k);
|
||||
}
|
||||
unset($v);
|
||||
} elseif (is_string($node) && $parentKey !== null && ! in_array($parentKey, $skipKeys, true)) {
|
||||
$new = preg_replace_callback($pattern, function ($m) use ($wordMap, &$replacements) {
|
||||
$replacements++;
|
||||
|
||||
return $wordMap[$m[1]];
|
||||
}, $node);
|
||||
if ($new !== null) {
|
||||
$node = $new;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$walk($json);
|
||||
|
||||
file_put_contents(
|
||||
$file,
|
||||
json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)."\n"
|
||||
);
|
||||
|
||||
echo 'Wort-Ersetzungen: '.$replacements.PHP_EOL;
|
||||
echo 'Datei gespeichert: '.$file.PHP_EOL;
|
||||
Loading…
Add table
Add a link
Reference in a new issue