setFileType('xlf');
parent::init($file, $path, $metaFile);
}
/**
* calls the parent function and convert all values from utf-8 to the original charset
*
* @return void
* @throws LFException raised if the parent read file method fails
*/
public function readFile() {
$this->readXlfFile();
foreach ($this->localLang['default'] as $constant => $value) {
if (empty($value)) {
$this->localLang['default'][$constant] = '';
}
}
}
/**
* reads a language file
*
* @param string $file language file
* @param string $langKey language shortcut
* @return array language content
* @throws LFException thrown if no data can be found
*/
protected function readLLFile($file, $langKey) {
if (!\is_file($file)) {
throw new LFException('failure.select.noLangfile');
}
// LIBXML_NOCDATA treat CDATA node as text node.
// htmlentities in CDATA are not modified,
// and those - normaly encoded if XML is valid - outside CDATA will be decoded.
$xmlContent = \simplexml_load_string(\file_get_contents($file), \SimpleXMLElement::class, LIBXML_NOCDATA);
// Cast XML to associative array with json_decode/encode.
// This way, value is XML are casted to string.
$xmlContent = \json_decode(\json_encode($xmlContent), TRUE);
// check data
if (!\is_array($xmlContent['file']['body'])) {
throw new LFException('failure.search.noFileContent', 0, '(' . $file . ')');
}
if ($langKey === 'default') {
$this->meta = $xmlContent['file']['header'] ?? [];
}
$this->meta['@attributes'] = $xmlContent['file']['@attributes'];
return $xmlContent['file']['body'];
}
/**
* Resolves the trans-unit parts of the xlf language files into flat
* source arrays with the target language or the source if the target is en
*
* @param array $sourceData
* @return array
*/
public function resolveTranslationUnitsArrayIntoFlatArray(array $sourceData) {
$flatData = [];
if (isset($sourceData['trans-unit']['@attributes'])) {
$sourceData['trans-unit'] = [$sourceData['trans-unit']];
}
if (!array_key_exists('trans-unit', $sourceData)) {
return $flatData;
}
foreach ((array) $sourceData['trans-unit'] as $data) {
if (isset($data['@attributes']['id'])) {
$constant = $data['@attributes']['id'];
if (array_key_exists('target', $data)) {
$flatData[$constant] = $data['target'];
} else {
$flatData[$constant] = $data['source'];
}
if (empty($flatData[$constant])) {
$flatData[$constant] = '';
}
}
}
return $flatData;
}
/**
* Reads the absolute language file with all localized sub files
*
* @return void
* @throws LFException
*/
public function readXlfFile() {
$localLang = [];
// read absolute file
$localLang['default'] = $this->readLLFile($this->absFile, 'default');
$localLang['default'] = $this->resolveTranslationUnitsArrayIntoFlatArray($localLang['default']);
// loop all languages
$originLang = [];
$languages = SgLib::getSystemLanguages();
foreach ($languages as $lang) {
$originLang[$lang] = $this->absFile;
if ($lang === 'default') {
continue;
}
// get localized file
$content = array_key_exists($lang, $localLang) ? $localLang[$lang] : '';
$lFile = $this->getLocalizedFile($content, $lang);
if ($this->checkLocalizedFile(\basename($lFile), $lang)) {
$originLang[$lang] = $lFile;
$localLang[$lang] = [];
if (!\is_file($lFile)) {
continue;
}
// read the content
$localSubLanguage = $this->readLLFile($lFile, $lang);
$localLang[$lang] = $this->resolveTranslationUnitsArrayIntoFlatArray($localSubLanguage);
// merge arrays and save origin of current language
ArrayUtility::mergeRecursiveWithOverrule($localLang, $localSubLanguage);
}
}
// copy all to object variables, if everything was ok
$this->localLang = $localLang;
$this->originLang = $originLang;
}
/**
* checks the localLang array to find localized version of the language
* (checks l10n directory too)
*
* @param string $content language content (only one language)
* @param string $langKey language shortcut
* @return string localized file (absolute)
*/
protected function getLocalizedFile($content, $langKey) {
$file = '';
if ($this->session->getDataByKey('editingMode') !== 'extension') {
$file = $this->getLocalizedFileName($this->absFile, $langKey);
}
if (!\is_file($file)) {
$file = \dirname($this->absFile) . '/' . $this->nameLocalizedFile($langKey);
}
return Typo3Lib::fixFilePath($file);
}
/**
* checks a filename if its a localized file reference
*
* @param string $filename
* @param string $langKey language shortcut
* @return boolean true(localized) or false
*/
public function checkLocalizedFile($filename, $langKey) {
if (!\preg_match('/^(' . $langKey . ')\..*\.xlf$/', $filename)) {
return FALSE;
}
return TRUE;
}
/**
* get the name of a localized file
*
* @param string $langKey language shortcut
* @return string localized file (only filename)
*/
public function nameLocalizedFile($langKey) {
return $langKey . '.' . \basename($this->relFile);
}
/**
* generates the xml header
*
* @return string xml header
*/
private function getXMLHeader() {
return '' . "\n";
}
/**
* converts the array to a xml string
*
* @param array $phpArray
* @param string $targetLanguage
* @param array $enLanguage
* @return string xml content
*/
private function array2xml($phpArray, $targetLanguage, $enLanguage) {
$targetLanguage = \htmlspecialchars($targetLanguage);
$targetLanguageAttribute = ($targetLanguage !== 'default' ? ' target-language="' . $targetLanguage . '"' : '');
$lfeditorExtConf = ExtensionUtility::getExtensionConfiguration();
$date = ($lfeditorExtConf['changeXlfDate'] ? \gmdate('Y-m-d\TH:i:s\Z') : $this->meta['@attributes']['date']);
$xmlString = $this->getXMLHeader() . '