Sprach-INI Dateien synchronisieren, säubern, sortieren. language
Spaghetticode! Kein Luxus! Code-Schnipsel vergleicht zwei Ländervarianten einer Joomla-Sprachdatei, z.B. en-GB.plg_system_example.ini (im Code die $mama
) und de-DE.plg_system_example.ini (im Code das $child
).
Voraussetzungen
- Die Dateien müssen dem ini-Standard entsprechen, also 1 Zeile pro Sprachstring.
PLG_EXAMPLE_OPTIONAL="(optional)"
. Keine Zeilenumbrüche etc. - Die Sprachdateien befinden sich im einzutragenden
$langsPath
in Unterordnern wie in Joomla üblich, z.B.en-GB/
undde-DE/.
- Benötigt ggf. Anpassungen für Joomla 4, da dort der Dateinamen-Prefix, z.B.
de-DE.
, auch weggelassen werden darf.
Was es tut
- Die Sprachstring-Platzhalter werden vom Skript alphabetisch sortiert.
- Fehlende Sprachstring-Platzhalter, die in der
$mama
, existieren, aber im$child
fehlen, werden ins's$child
kopiert, mit einem Prefix-Kommentar;;NOT-FOUND-IN-child;;
. Der Code geht also davon aus, dass die$mama
bereits vollständig ist. Natürlich kann man für einen Gegentest$mama
und$child
austauschen im Skript. - Doppelte Sprach-Platzhalter, gefunden in der selben Datei, brechen den Code ab mit einem entsprechenden Hinsweis
DOPPELTER key xyz in Datei abc
. - Wo identische Übersetzungen für den selben Sprachstringplatzhalter gefunden werden, erfolgt am Ende eine Ausgabe
Folgende eventuell nicht übersetzt? In beiden Dateien gleich.
- Veraltete Double-Quote-Platzhalter
"__QQ__"
werden in\"
umgewandelt. - Erzeugt Kopien der Original-Sprachdateien, z.B. en-GB.plg_system_example-copy.ini für händische Kontrolle und Nacharbeit und ggf. Copy&Paste in die Originale.
Ausgabe und Skript
Gerenderte Ausgabe der Datei language-files-synchronize.php
$mama, $child und $xyz-copy
Original $mama: /media/php-includes_ghsvs/language/en-GB/en-GB.plg_system_example.ini
Copy $mama: /media/php-includes_ghsvs/language/en-GB/en-GB.plg_system_example-copy.ini
----------
Original $child: /media/php-includes_ghsvs/language/de-DE/de-DE.plg_system_example.ini
Copy $child: /media/php-includes_ghsvs/language/de-DE/de-DE.plg_system_example-copy.ini
----------
Folgende eventuell nicht übersetzt? In beiden Dateien gleich.
Array ( [PLG_A_EXAMPLE_DESC5] => Example. [PLG_B_EXAMPLE_DESC4] => Ding dong dang. [PLG_EXAMPLE_DESC] => Extremly \"reduced\" in blah. )
Quelltext der Datei language-files-synchronize.php
<?php
\defined('_JEXEC') or die;
use Joomla\CMS\Uri\Uri;
### Konfiguration START.
// Verzeichnis mit Sprachdateien.
$langsPath = '/media/php-includes_ghsvs/language/';
// Mitteleil der Dateien. Bspw. in 'en-GB.plg_system_example ini'.
// Auch denkbar für .sys.ini-Dateien: 'plg_system_example.sys'.
$filePart = 'plg_system_example';
// $mama ist die Referenz für $child.
$mama = 'en-GB';
$child = 'de-DE';
// Ich bevorzuge Leerzeilen zwischen den Einzelzeilern.
$outputLineEndings = "\n\n";
// Dateinamen-Postfix für die bearbeiteten Dateien.
$copiedFileEnding = '-copy';
### Konfiguration ENDE.
$sepa = '|-[x::SEPA-CHECKER::]-|';
$mamaFile = $langsPath . $mama . '/' . $mama . '.' . $filePart;
$mamaFileAbs = JPATH_SITE . $mamaFile;
$mamaLines = file($mamaFileAbs . '.ini',
FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$mamaStrings = parse_ini_file($mamaFileAbs . '.ini');
$mamaLinesDoubleCheck = $sepa . implode($sepa, $mamaLines);
foreach ($mamaStrings as $key => $string)
{
if (substr_count($mamaLinesDoubleCheck, $sepa . $key . '=') > 1)
{
echo "DOPPELTER key in $mamaFile : " . PHP_EOL . $key . PHP_EOL . PHP_EOL;
exit;
}
}
$childFile = $langsPath . $child . '/' . $child . '.' . $filePart;
$childFileAbs = JPATH_SITE . $childFile;
$childLines = file($childFileAbs . '.ini',
FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$childStrings = parse_ini_file($childFileAbs . '.ini');
$childLinesDoubleCheck = $sepa . implode($sepa, $childLines);
foreach ($childStrings as $key => $string)
{
if (substr_count($childLinesDoubleCheck, $sepa . $key . '=') > 1)
{
echo "DOPPELTER key in $childFile : " . PHP_EOL . $key . PHP_EOL . PHP_EOL;
exit;
}
}
$collectChilds = array();
ksort($mamaStrings);
foreach ($mamaStrings as $key => $string)
{
$mamaStrings[$key] = str_replace(array('"_QQ_"', '"'), '_QQ_', $string);
}
foreach ($childStrings as $key => $string)
{
$childStrings[$key] = str_replace(array('"_QQ_"', '"'), '_QQ_', $string);
}
$collectIdenticals = array();
foreach ($mamaStrings as $key => $string)
{
$mamaStrings[$key] = $key . '="' . str_replace('_QQ_', '\"', $string) . '"';
if (!isset($childStrings[$key]))
{
$collectChilds[] = ';;NOT-FOUND-IN-child;;' . $key . '="'
. str_replace('_QQ_', '\"', $string) . '"';
}
else
{
if ($string === $childStrings[$key])
{
$collectIdenticals[$key] = htmlspecialchars(str_replace('_QQ_', '\"',
$string));
}
$collectChilds[] = $key . '="' . str_replace('_QQ_', '\"',
$childStrings[$key]) . '"';
}
}
file_put_contents($childFileAbs . $copiedFileEnding . '.ini',
implode($outputLineEndings, $collectChilds));
file_put_contents($mamaFileAbs . $copiedFileEnding . '.ini',
implode($outputLineEndings, $mamaStrings));
echo '<h5>$mama, $child und $xyz-copy</h5>' . PHP_EOL;
$version = '?v=' . time();
$dings = '<p>Original $mama: <a href="' . Uri::root()
. ltrim($mamaFile . '.ini', '/') . '">'
. $mamaFile . '.ini' . '</a><br>' . PHP_EOL;
$dings .= 'Copy $mama: <a href="' . Uri::root()
. ltrim($mamaFile . $copiedFileEnding . '.ini' . $version, '/') . '">'
. $mamaFile . $copiedFileEnding . '.ini' . '</a><br>' . PHP_EOL;
$dings .= '----------<br>' . PHP_EOL ;
$dings .= 'Original $child: <a href="' . Uri::root()
. ltrim($childFile . '.ini', '/') . '">'
. $childFile . '.ini' . '</a><br>' . PHP_EOL;
$dings .= 'Copy $child: <a href="' . Uri::root()
. ltrim($childFile . $copiedFileEnding . '.ini' . $version, '/') . '">'
. $childFile . $copiedFileEnding . '.ini' . '</a><br>' . PHP_EOL;
$dings .= '----------<br>' . PHP_EOL . '</p>' ;
echo $dings;
echo '<h5>Folgende eventuell nicht übersetzt? In beiden Dateien gleich.</h5>'
. PHP_EOL;
echo '<pre>' . print_r($collectIdenticals, true) . '</pre>' . PHP_EOL;