dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
dbxLanguageVariants_test.php
Go to the documentation of this file.
1<?php
2
10
11$moduleRoot = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'modules';
12$errors = array();
13$candidates = array();
14$extensions = array('htm', 'html', 'tpl', 'txt', 'svg');
15$germanPattern = '/[äöüÄÖÜß]'
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';
27$iterator = new RecursiveIteratorIterator(
28 new RecursiveDirectoryIterator($moduleRoot, FilesystemIterator::SKIP_DOTS)
29);
30
31foreach ($iterator as $file) {
32 $path = str_replace('\\', '/', $file->getPathname());
33 $extension = strtolower($file->getExtension());
34 if (
35 !$file->isFile() ||
36 !str_contains($path, '/tpl/') ||
37 !in_array($extension, $extensions, true)
38 ) {
39 continue;
40 }
41
42 $stem = pathinfo($file->getFilename(), PATHINFO_FILENAME);
43 if (preg_match('/_(en|es)$/i', $stem)) {
44 continue;
45 }
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;
50
51 if (!isset($candidates[$key]) || $explicitGerman) {
52 $candidates[$key] = array(
53 'source' => $file->getPathname(),
54 'target_base' => $file->getPath()
55 . DIRECTORY_SEPARATOR . $baseStem,
56 'extension' => $extension,
57 'explicit' => $explicitGerman,
58 );
59 }
60}
61
62$extract = static function (string $pattern, string $content, int $group = 0): array {
63 preg_match_all($pattern, $content, $matches);
64 return $matches[$group] ?? array();
65};
66$markerPattern = '/\‍[(?:\/?(?:modul|inc)\b[^\‍]]*|tpl[^\‍]]*|'
67 . '(?:dbx|rpt|cms):[^\‍]]+)\‍]/i';
68$placeholderPattern = '/\{\{[A-Za-z_][A-Za-z0-9_]*\}[A-Za-z0-9_]*'
69 . '|\{(?:[A-Za-z_][A-Za-z0-9_.:-]*|\$ref:[^{}]+)\}/';
70$tagPattern = '/<\/?\s*([A-Za-z][A-Za-z0-9:-]*)\b/';
71$urlPattern = '/\b(?:href|src|action)\s*=\s*([\'"])(.*?)\1/is';
72$moduleBlockPattern = '/(\‍[(modul)\b[^\‍]]*\‍])(.*?)(\‍[\/\2\‍])/is';
73$normalizedModuleBlocks = static function (string $content) use ($moduleBlockPattern): array {
74 preg_match_all($moduleBlockPattern, $content, $matches, PREG_SET_ORDER);
75 $blocks = array();
76 foreach ($matches as $match) {
77 $body = preg_replace(
78 '/((?:^|&)label=)[^&]*/i',
79 '$1{translated-label}',
80 $match[3]
81 );
82 $blocks[] = $match[1] . $body . $match[4];
83 }
84 return $blocks;
85};
87
88foreach ($candidates as $candidate) {
89 $source = (string)file_get_contents($candidate['source']);
90 if (!$candidate['explicit'] && !preg_match($germanPattern, $source)) {
91 continue;
92 }
93
94 $checked++;
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';
100 continue;
101 }
102
103 $target = (string)file_get_contents($targetPath);
104 foreach (array(
105 'technische Marker' => array($markerPattern, 0),
106 'Platzhalter' => array($placeholderPattern, 0),
107 'HTML-Tagfolge' => array($tagPattern, 1),
108 'URL-Attribute' => array($urlPattern, 2),
109 ) as $label => $rule) {
110 $sourceParts = $extract($rule[0], $source, $rule[1]);
111 $targetParts = $extract($rule[0], $target, $rule[1]);
112 if ($label === 'technische Marker') {
113 $normalizeCmsRoot = static fn(string $marker): string => preg_replace(
114 '/(\‍[cms:root=)[^&\‍]]+/i',
115 '$1{translated-root}',
116 $marker
117 ) ?? $marker;
118 $sourceParts = array_map($normalizeCmsRoot, $sourceParts);
119 $targetParts = array_map($normalizeCmsRoot, $targetParts);
120 }
121 if ($sourceParts !== $targetParts) {
122 $errors[] = $targetPath . ': ' . $label . ' verändert';
123 }
124 }
126 $errors[] = $targetPath . ': Modul-Block technisch verändert';
127 }
128 }
129}
130
132foreach ($iterator = new RecursiveIteratorIterator(
133 new RecursiveDirectoryIterator($moduleRoot, FilesystemIterator::SKIP_DOTS)
134) as $file) {
135 if (!$file->isFile() || !preg_match('/_(de|en|es)\.dd\.php$/', $file->getFilename(), $match)) {
136 continue;
137 }
138 $path = str_replace('\\', '/', $file->getPathname());
139 if (!str_contains($path, '/dd/')) {
140 continue;
141 }
142
144 $table = array();
145 $fields = array();
146 $indexes = array();
147 include $file->getPathname();
148 $language = strtolower($match[1]);
149 if (
150 strtolower((string)($table['language'] ?? '')) !== $language ||
151 !preg_match('/_' . preg_quote($language, '/') . '$/i', (string)($table['table'] ?? ''))
152 ) {
153 $errors[] = $path
154 . ': Sprach-DD verweist nicht auf eine echte Sprachversionstabelle';
155 }
156}
157
158if ($checked === 0) {
159 $errors[] = 'Keine deutschen Templatequellen gefunden';
160}
161if ($languageDdCount === 0) {
162 $errors[] = 'Keine echten Sprach-DDs gefunden';
163}
165 fwrite(
166 STDERR,
167 "Sprachvarianten-Prüfung fehlgeschlagen:\n - "
168 . implode("\n - ", array_unique($errors)) . "\n"
169 );
170 exit(1);
171}
172
173echo "OK: {$checked} Templategruppen sind strukturgleich übersetzt; "
174 . "{$languageDdCount} Sprach-DDs verweisen auf echte Sprachtabellen.\n";
$table['server']
Definition .dd.php:6
$indexes[]
Definition .dd.php:167
foreach($candidates as $candidate) $languageDdCount
foreach($iterator as $file) $extract
exit
Definition index.php:146