Alte TYPO3 Sprachdateien (XML) in neue konvertieren (XLF)

Beim TYPO3 Update von alten Versionen kann es sein, dass noch XML Sprachdateien verwendet werden, die in aktuellen Versionen nicht mehr unterstützt werden. Folgendes Script kann verwendet werden, um diese Sprachdateien von XML in XLF zu konvertieren.

Im Input Feld kann z.B. der Inhalt der vorhandenen locallang.xml kopiert werden. Für jede Übersetzung erhält man eine eigene Ausgabe.
Wären beispielsweise Deutsch und Englisch als Übersetzung angelegt, würde die Ausggaben gespeichert werden unter:

  • locallang.xlf
  • de.locallang.xlf
  • en.locallang.xlf
<?php
function convertXml2xlf($data, $language, $translations = array()) {
    $xml = new DOMDocument('1.0', 'UTF-8');
    $xliff = $xml->createElement('xliff');
    $xliff->setAttribute('version', '1.0');
    $file = $xml->createElement('file');
    $file->setAttribute('source-language', 'en');
    if (func_num_args() > 2) {
        $file->setAttribute('target-language', $language);
    }
    $file->setAttribute('datatype', 'plaintext');
    $file->setAttribute('original', 'messages');
    $file->setAttribute('data', strftime('%Y-%m-%dT%H-%M-%S'));
    $file->setAttribute('product-name', 'zsb');
    $header = $xml->createElement('header');
    $file->appendChild($header);
    $body = $xml->createElement('body');
    foreach ($data as $index => $label) {
        $unit = $xml->createElement('trans-unit');
        $unit->setAttribute('id', $index);
        $unit->setAttribute('xml:space', 'preserve');
        $source = $xml->createElement('source', $label);
        $unit->appendChild($source);
        if (func_num_args() > 2) {
            $target = $xml->createElement('target', $translations[$index]);
            $unit->appendChild($target);
        }
        $body->appendChild($unit);
    }
    $file->appendChild($body);
    $xliff->appendChild($file);
    $xml->appendChild($xliff);
    return $xml->saveXML();
}
if (isset($_POST['xml'])) {
    $xml = $_POST['xml'];
    $xml = utf8_encode($xml);
    $doc = new DOMDocument();
    $doc->loadXML($xml);
    $defaults = array();
    $langs    = array();
    $xpath = new DOMXPath($doc);
    $languages = $xpath->query("//T3locallang/data/languageKey");
    foreach ($languages as $language) {
        $lang = $language->attributes['index']->value;
        if ($lang !== 'default') {
            $langs[$lang] = array();
        }
        foreach ($language->childNodes as $word) {
            if ($word->nodeName !== 'label') {
                continue;
            }
            $string      = utf8_decode($word->attributes['index']->value);
            $translation = utf8_decode($word->nodeValue);
            if ($lang === 'default') {
                $defaults[$string] = $translation;
            } else {
                $langs[$lang][$string] = $translation;
            }
        }
    }
    $outputs = array(
        'locallang.xlf' => convertXml2xlf($defaults, 'en'),
    );
    foreach ($langs as $lang => $words) {
        $outputs[$lang . '.locallang.xlf'] = convertXml2xlf($defaults, $lang, $words);
    }
}
?>
<!DOCTYPE html>
<html>
<head>
    <title>LocalLang: XML to XLIFF</title>
    <style>
        textarea {
            box-sizing: border-box;
            height: 250px;
            width: 100%;
        }
    </style>
</head>
<body>
<form action="<?= $_SERVER['PHP_SELF'] ?>" method="post">
    <fieldset>
        <legend>Input locallang.xml</legend>
        <textarea name="xml" style="width: 100%; height: 250px;"><?= htmlspecialchars(@$_POST['xml']) ?></textarea>
    </fieldset>
    
<input type="submit">
</form> <?php if (isset($outputs)): ?>
<?php foreach ($outputs as $file => $xml): ?> <fieldset> <legend><?= $file ?></legend> <textarea onfocus="this.select()"><?= htmlspecialchars($xml) ?></textarea> </fieldset> <?php endforeach; ?> <?php endif; ?> </body> </html>

Das Original findet sich hier:
gist.github.com/tleilax/da6bb47f81e20a4d8edf

Beispiel

Hier ein Beispieil einer alten TYPO3 locallang.xml Datei:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3locallang>
		<type>module</type>
		<description>Language labels for plugin "tx_t3locations_pi1"</description>
	<data type="array">
		<languageKey index="default" type="array">
			
			
			
			
			
		</languageKey>
		<languageKey index="de" type="array">
			
			
			
			
			
		</languageKey>
		<languageKey index="en" type="array">
			
			
			
			
			
		</languageKey>
	</data>
</T3locallang>

Sie wird konvertiert in:

<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.0">
    <file source-language="en" datatype="plaintext" original="messages" data="2023-10-13T12-24-32" product-name="zsb">
        
<body> <trans-unit id="choose_country" xml:space="preserve"><source>Please choose country</source></trans-unit> <trans-unit id="choose_location" xml:space="preserve"><source>Please choose city</source></trans-unit> <trans-unit id="all_countries" xml:space="preserve"><source>All countries</source></trans-unit> <trans-unit id="localtime" xml:space="preserve"><source>local time</source></trans-unit> <trans-unit id="more" xml:space="preserve"><source>more</source></trans-unit> </body> </file> </xliff>
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.0">
    <file source-language="en" target-language="de" datatype="plaintext" original="messages" data="2023-10-13T12-24-32"
          product-name="zsb">
        
<body> <trans-unit id="choose_country" xml:space="preserve"> <source>Bitte Land auswählen</source> <target>Bitte Land auswählen</target> </trans-unit> <trans-unit id="choose_location" xml:space="preserve"> <source>Bitte Ort auswählen</source> <target>Bitte Ort auswählen</target> </trans-unit> <trans-unit id="all_countries" xml:space="preserve"> <source>Alle Länder</source> <target>Alle Länder</target> </trans-unit> <trans-unit id="localtime" xml:space="preserve"> <source>Ortszeit</source> <target>Ortszeit</target> </trans-unit> <trans-unit id="more" xml:space="preserve"> <source>Mehr</source> <target>Mehr</target> </trans-unit> </body> </file> </xliff>
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.0">
    <file source-language="en" target-language="en" datatype="plaintext" original="messages" data="2023-10-13T12-24-32"
          product-name="zsb">
        
<body> <trans-unit id="choose_country" xml:space="preserve"> <source>Bitte Land auswählen</source> <target>Please choose country</target> </trans-unit> <trans-unit id="choose_location" xml:space="preserve"> <source>Bitte Ort auswählen</source> <target>Please choose city</target> </trans-unit> <trans-unit id="all_countries" xml:space="preserve"> <source>Alle Länder</source> <target>All countries</target> </trans-unit> <trans-unit id="localtime" xml:space="preserve"> <source>Ortszeit</source> <target>local time</target> </trans-unit> <trans-unit id="more" xml:space="preserve"> <source>Mehr</source> <target>more</target> </trans-unit> </body> </file> </xliff>

Erstellt am: