11$moduleRoot = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR .
'modules';
16 .
'|(?:benutzer|registrier|speicher|lösch|loesch|bearbeit|beschreib|'
17 .
'bezeichn|einstell|erstell|aktualis|auswähl|auswaehl|datei|deutsch|'
18 .
'daten|druck|ausdruck|eintrag|erfolg|fehlermeld|formular|hinweis|'
19 .
'kontaktanfrag|kontaktdaten|userdaten|zugangsdaten|hinzufüg|'
20 .
'hinzufueg|einfueg|öffnen|oeffnen|workflow\s+abgeschlossen)'
21 .
'|\b(?:aber|abbrechen|alle|anzeigen|artikel|auswahl|bearbeiten|'
22 .
'beschreibung|bitte|der|die|ein|eine|einstellungen|fehler|felder|'
23 .
'für|fuer|gruppe|hilfe|ihre|inhalt|kein|keine|keiner|löschen|'
24 .
'loeschen|menü|menue|neu|neue|neuer|neues|nicht|oder|ordner|seite|'
25 .
'seiten|speichern|suche|suchen|titel|über|ueber|und|wählen|waehlen|'
26 .
'weiter|wird|zurück|zurueck)\b/iu';
28 new RecursiveDirectoryIterator(
$moduleRoot, FilesystemIterator::SKIP_DOTS)
32 $path = str_replace(
'\\',
'/',
$file->getPathname());
33 $extension = strtolower(
$file->getExtension());
36 !str_contains($path,
'/tpl/') ||
42 $stem = pathinfo(
$file->getFilename(), PATHINFO_FILENAME);
43 if (preg_match(
'/_(en|es)$/i', $stem)) {
46 $explicitGerman = (bool)preg_match(
'/_de$/i', $stem);
47 $baseStem = $explicitGerman ? preg_replace(
'/_de$/i',
'', $stem) : $stem;
48 $key = str_replace(
'\\',
'/',
$file->getPath())
49 .
'/' . $baseStem .
'.' . $extension;
53 'source' =>
$file->getPathname(),
54 'target_base' =>
$file->getPath()
55 . DIRECTORY_SEPARATOR . $baseStem,
56 'extension' => $extension,
57 'explicit' => $explicitGerman,
63 preg_match_all($pattern,
$content, $matches);
64 return $matches[$group] ?? array();
67 .
'(?:dbx|rpt|cms):[^\]]+)\]/i';
69 .
'|\{(?:[A-Za-z_][A-Za-z0-9_.:-]*|\$ref:[^{}]+)\}/';
71$urlPattern =
'/\b(?:href|src|action)\s*=\s*([\'"])(.*?)\1/is';
76 foreach ($matches as $match) {
78 '/((?:^|&)label=)[^&]*/i',
79 '$1{translated-label}',
82 $blocks[] = $match[1] .
$body . $match[4];
89 $source = (string)file_get_contents($candidate[
'source']);
95 foreach (array(
'en',
'es') as $language) {
96 $targetPath = $candidate[
'target_base'] .
'_' . $language
97 .
'.' . $candidate[
'extension'];
98 if (!is_file($targetPath)) {
99 $errors[] = $targetPath .
': Sprachdatei fehlt';
103 $target = (string)file_get_contents($targetPath);
109 ) as $label =>
$rule) {
112 if ($label ===
'technische Marker') {
113 $normalizeCmsRoot =
static fn(
string $marker):
string => preg_replace(
114 '/(\[cms:root=)[^&\]]+/i',
115 '$1{translated-root}',
118 $sourceParts = array_map($normalizeCmsRoot, $sourceParts);
119 $targetParts = array_map($normalizeCmsRoot, $targetParts);
121 if ($sourceParts !== $targetParts) {
122 $errors[] = $targetPath .
': ' . $label .
' verändert';
126 $errors[] = $targetPath .
': Modul-Block technisch verändert';
132foreach (
$iterator =
new RecursiveIteratorIterator(
133 new RecursiveDirectoryIterator(
$moduleRoot, FilesystemIterator::SKIP_DOTS)
135 if (!
$file->isFile() || !preg_match(
'/_(de|en|es)\.dd\.php$/',
$file->getFilename(), $match)) {
138 $path = str_replace(
'\\',
'/',
$file->getPathname());
139 if (!str_contains($path,
'/dd/')) {
147 include
$file->getPathname();
148 $language = strtolower($match[1]);
150 strtolower((
string)(
$table[
'language'] ??
'')) !== $language ||
151 !preg_match(
'/_' . preg_quote($language,
'/') .
'$/i', (
string)(
$table[
'table'] ??
''))
154 .
': Sprach-DD verweist nicht auf eine echte Sprachversionstabelle';
159 $errors[] =
'Keine deutschen Templatequellen gefunden';
162 $errors[] =
'Keine echten Sprach-DDs gefunden';
167 "Sprachvarianten-Prüfung fehlgeschlagen:\n - "
168 . implode(
"\n - ", array_unique(
$errors)) .
"\n"
173echo
"OK: {$checked} Templategruppen sind strukturgleich übersetzt; "
174 .
"{$languageDdCount} Sprach-DDs verweisen auf echte Sprachtabellen.\n";
foreach($candidates as $candidate) $languageDdCount
foreach($iterator as $file) $extract