‪TYPO3CMS  ‪main
updateIsoDatabase.php
Go to the documentation of this file.
1 #!/usr/bin/env php
2 <?php
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 use Symfony\Component\Translation\Loader\PoFileLoader;
19 use Symfony\Component\Translation\MessageCatalogue;
22 
23 if (PHP_SAPI !== 'cli') {
24  die('Script must be called from command line.' . chr(10));
25 }
26 
27 require __DIR__ . '/../../vendor/autoload.php';
28 
29 // Basic Information
30 // * ISO 639-1 -> languages in two letter code
31 // * ISO 639-2 -> languages in two/three letter code
32 // * ISO 3166-1 -> countries
33 // * ISO 3166-2 -> regions in countries (= states)
34 // * ISO 15924 - 4-letter language script system
35 
40 class ‪XliffDumper extends \Symfony\Component\Translation\Dumper\XliffFileDumper
41 {
42  public function ‪dump(MessageCatalogue $messages, array $options = []): void
43  {
44  if ($messages->getLocale() === 'en') {
45  $this->setRelativePathTemplate('%domain%.%extension%');
46  } else {
47  $this->setRelativePathTemplate('%locale%.%domain%.%extension%');
48  }
49  parent::dump($messages, $options);
50  }
51 
52  public function ‪formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
53  {
54  $isBaseLanguage = $messages->getLocale() === 'en';
55  $dom = new \DOMDocument('1.0', 'utf-8');
56  $dom->formatOutput = true;
57 
58  $xliff = $dom->appendChild($dom->createElement('xliff'));
59  $xliff->setAttribute('version', '1.2');
60  $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2');
61 
62  $xliffFile = $xliff->appendChild($dom->createElement('file'));
63  $xliffFile->setAttribute('source-language', 'en');
64  if (!$isBaseLanguage) {
65  $xliffFile->setAttribute('target-language', str_replace('_', '-', $messages->getLocale()));
66  }
67  $xliffFile->setAttribute('datatype', 'plaintext');
68  $xliffFile->setAttribute('original', 'EXT:core/Resources/Private/Language/countries.xlf');
69  $xliffFile->setAttribute('product-name', 'typo3/cms-core');
70 
71  $xliffBody = $xliffFile->appendChild($dom->createElement('body'));
72  foreach ($messages->all($domain) as $source => $target) {
73  $translation = $dom->createElement('trans-unit');
74 
75  $translation->setAttribute('id', $source);
76  $translation->setAttribute('resname', $source);
77 
78  $s = $translation->appendChild($dom->createElement('source'));
79  if ($isBaseLanguage) {
80  $s->appendChild($dom->createTextNode($target));
81  } else {
82  $translation->setAttribute('approved', 'yes');
83  $s->appendChild($dom->createTextNode($messages->getFallbackCatalogue()->get($source, $domain) ?: $source));
84  // Does the target contain characters requiring a CDATA section?
85  $text = preg_match('/[&<>]/', $target) === 1 ? $dom->createCDATASection($target) : $dom->createTextNode($target);
86 
87  $targetElement = $dom->createElement('target');
88  $t = $translation->appendChild($targetElement);
89  $t->appendChild($text);
90  }
91  $xliffBody->appendChild($translation);
92  }
93  return $dom->saveXML();
94  }
95 }
96 
97 // 0. Preparations
98 ‪$baseDirectory = __DIR__ . '/../../vendor/sokil/php-isocodes-db-i18n';
99 ‪$targetXliffDirectory = __DIR__ . '/../../typo3/sysext/core/Resources/Private/Language/Iso';
100 @mkdir(‪$targetXliffDirectory, 0777, true);
101 
102 // 1. Get all supported TYPO3 languages
104 ‪$languages = ‪$typo3Locales->getLanguages();
105 unset(‪$languages['default']);
107 
108 function ‪updatePhpFile(string $fileLocation, array $contents): void
109 {
110  ksort($contents, SORT_NATURAL);
111  $fileContents = file_get_contents($fileLocation);
112  $newFormattedData = ArrayUtility::arrayExport($contents);
113  $newFormattedData = str_replace("\n", "\n ", $newFormattedData);
114  $newFileContents = preg_replace('/private array \$rawData = (?:(?!];).)++];/us', 'private array $rawData = ' . $newFormattedData . ';', $fileContents);
115  file_put_contents($fileLocation, $newFileContents);
116 }
117 
119 {
120  sort(‪$countries);
121  $countryProviderFileLocation = __DIR__ . '/../../typo3/sysext/core/Classes/Country/CountryProvider.php';
122  $defaultCatalogue = new MessageCatalogue('en');
123  $xliffDumper = new ‪XliffDumper();
124 
125  $countriesByCountryCode = [];
126  foreach (‪$countries as $countryDetails) {
127  $countryCode = $countryDetails['alpha_2'];
128  unset($countryDetails['alpha_2']);
129  $countriesByCountryCode[$countryCode] = $countryDetails;
130  }
131  ksort($countriesByCountryCode);
132  // Add XLIFF labels
133  foreach ($countriesByCountryCode as $countryCode => $countryDetails) {
134  $defaultCatalogue->add([$countryCode . '.name' => $countryDetails['name']], 'countries');
135  if (isset($countryDetails['official_name'])) {
136  $defaultCatalogue->add([$countryCode . '.official_name' => $countryDetails['official_name']], 'countries');
137  }
138  }
139  ‪updatePhpFile($countryProviderFileLocation, $countriesByCountryCode);
140  // Dump original translations in XLIFF file
141  $xliffDumper->dump($defaultCatalogue, ['path' => ‪$targetXliffDirectory]);
142 
143  // 2. Load labels that are translated for countries ("name" and "official name")
144  $loader = new PoFileLoader();
145  foreach (‪$supportedLanguagesInTypo3 as $languageKey) {
146  $translationFile = ‪$baseDirectory . '/messages/' . $languageKey . '/LC_MESSAGES/3166-1.po';
147  if (!file_exists($translationFile)) {
148  continue;
149  }
150  $catalogue = $loader->load($translationFile, $languageKey);
151  $cleanedCatalogue = new MessageCatalogue(str_replace('_', '-', $languageKey));
152  $cleanedCatalogue->addFallbackCatalogue($defaultCatalogue);
153  foreach ($countriesByCountryCode as $countryCode => $countryDetails) {
154  $countryName = $countryDetails['name'];
155  $translatedCountryName = $catalogue->get($countryName);
156  if ($translatedCountryName) {
157  $cleanedCatalogue->add([$countryCode . '.name' => $translatedCountryName], 'countries');
158  }
159  if (isset($countryDetails['official_name'])) {
160  $countryName = $countryDetails['official_name'];
161  $translatedCountryName = $catalogue->get($countryName);
162  if ($translatedCountryName) {
163  $cleanedCatalogue->add([$countryCode . '.official_name' => $translatedCountryName], 'countries');
164  }
165  }
166  }
167  $xliffDumper->dump($cleanedCatalogue, ['path' => ‪$targetXliffDirectory]);
168  }
169 }
170 
171 // Load all available countries in english
172 ‪$countries = json_decode(file_get_contents(‪$baseDirectory . '/databases/iso_3166-1.json'), true);
174 
176 {
177  sort(‪$languages);
178  $providerFileLocation = __DIR__ . '/../../typo3/sysext/core/Classes/Localization/OfficialLanguages.php';
179  $defaultCatalogue = new MessageCatalogue('en');
180  $xliffDumper = new ‪XliffDumper();
181 
182  $cleanedLanguages = [];
183  foreach (‪$languages as $languageDetails) {
184  $alias = null;
185  if (isset($languageDetails['alpha_2'])) {
186  $primaryLanguageKey = $languageDetails['alpha_2'];
187  $alias = $languageDetails['alpha_3'] ?? null;
188  } else {
189  $primaryLanguageKey = $languageDetails['alpha_3'];
190  }
191  $data = ['name' => $languageDetails['name']];
192  if ($alias) {
193  $data['alias'] = $alias;
194  }
195  $cleanedLanguages[$primaryLanguageKey] = $data;
196  }
197  ksort($cleanedLanguages);
198  // Add XLIFF labels
199  foreach ($cleanedLanguages as $primaryLanguageKey => $languageData) {
200  $defaultCatalogue->add([$primaryLanguageKey => $languageData['name']], 'languages');
201  }
202  ‪updatePhpFile($providerFileLocation, $cleanedLanguages);
203  // Dump original translations in XLIFF file
204  $xliffDumper->dump($defaultCatalogue, ['path' => ‪$targetXliffDirectory]);
205 
206  // 2. Load labels
207  $loader = new PoFileLoader();
208  foreach (‪$supportedLanguagesInTypo3 as $languageKey) {
209  $translationFile = ‪$baseDirectory . '/messages/' . $languageKey . '/LC_MESSAGES/639-2.po';
210  if (!file_exists($translationFile)) {
211  continue;
212  }
213  $catalogue = $loader->load($translationFile, $languageKey);
214  $cleanedCatalogue = new MessageCatalogue(str_replace('_', '-', $languageKey));
215  $cleanedCatalogue->addFallbackCatalogue($defaultCatalogue);
216  foreach ($cleanedLanguages as $primaryLanguageKey => $countryDetails) {
217  $languageName = $countryDetails['name'];
218  $translatedName = $catalogue->get($languageName);
219  if ($translatedName) {
220  $cleanedCatalogue->add([$primaryLanguageKey => $translatedName], 'languages');
221  }
222  }
223  $xliffDumper->dump($cleanedCatalogue, ['path' => ‪$targetXliffDirectory]);
224  }
225 }
226 // Load all available languages in english
227 ‪$languageSource = json_decode(file_get_contents(‪$baseDirectory . '/databases/iso_639-2.json'), true);
229 
230 return;
231 
232 // Language Script Systems (ISO 15924)
233 // Currently XLIFF is disabled
235 {
236  ksort(‪$scripts);
237  $scriptsTargetFile = __DIR__ . '/../../typo3/sysext/core/Classes/Localization/LanguageScriptSystems.php';
238  $defaultCatalogue = new MessageCatalogue('en');
239  $loader = new PoFileLoader();
240  $xliffDumper = new ‪XliffDumper();
241  $scriptsByScriptCode = [];
242  foreach (‪$scripts as $scriptDetails) {
243  $scriptCode = $scriptDetails['alpha_4'];
244  unset($scriptDetails['alpha_4']);
245  $scriptsByScriptCode[$scriptCode] = $scriptDetails;
246  }
247  ksort($scriptsByScriptCode);
248  foreach ($scriptsByScriptCode as $scriptCode => $scriptDetails) {
249  $defaultCatalogue->add([$scriptCode => $scriptDetails['name']], 'language-script-systems');
250  }
251 
252  ‪updatePhpFile($scriptsTargetFile, $scriptsByScriptCode);
253  //$xliffDumper->dump($defaultCatalogue, ['path' => $targetXliffDirectory]);
254 
255  // Translated scripts
256  foreach (‪$supportedLanguagesInTypo3 as $languageKey) {
257  $translationFile = ‪$baseDirectory . '/messages/' . $languageKey . '/LC_MESSAGES/15924.po';
258  if (!file_exists($translationFile)) {
259  continue;
260  }
261  $catalogue = $loader->load($translationFile, $languageKey);
262  $cleanedCatalogue = new MessageCatalogue(str_replace('_', '-', $languageKey));
263  $cleanedCatalogue->addFallbackCatalogue($defaultCatalogue);
264  foreach ($scriptsByScriptCode as $scriptCode => $scriptDetails) {
265  $translatedName = $catalogue->get($scriptDetails['name']);
266  if ($translatedName) {
267  $cleanedCatalogue->add([$scriptCode => $translatedName], 'language-script-systems');
268  }
269  }
270  if ($cleanedCatalogue->all() !== []) {
271  //$xliffDumper->dump($cleanedCatalogue, ['path' => $targetXliffDirectory]);
272  }
273  }
274 }
275 
276 ‪$scripts = json_decode(file_get_contents(‪$baseDirectory . '/databases/iso_15924.json'), true);
‪importLanguages
‪importLanguages(array $languages, array $supportedLanguagesInTypo3, string $baseDirectory, string $targetXliffDirectory)
Definition: updateIsoDatabase.php:175
‪$countries
‪$countries
Definition: updateIsoDatabase.php:172
‪$languages
‪$languages
Definition: updateIsoDatabase.php:104
‪$languageSource
‪$languageSource
Definition: updateIsoDatabase.php:227
‪$baseDirectory
‪$baseDirectory
Definition: updateIsoDatabase.php:98
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:36
‪updatePhpFile
‪updatePhpFile(string $fileLocation, array $contents)
Definition: updateIsoDatabase.php:108
‪importCountries
‪importCountries(array $countries, array $supportedLanguagesInTypo3, string $baseDirectory, string $targetXliffDirectory)
Definition: updateIsoDatabase.php:118
‪$scripts
‪$scripts
Definition: updateIsoDatabase.php:276
‪$typo3Locales
‪$typo3Locales
Definition: updateIsoDatabase.php:103
‪XliffDumper
Definition: updateIsoDatabase.php:41
‪importLanguageScriptSystems
‪importLanguageScriptSystems(array $scripts, array $supportedLanguagesInTypo3, string $baseDirectory, string $targetXliffDirectory)
Definition: updateIsoDatabase.php:234
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:26
‪XliffDumper\dump
‪dump(MessageCatalogue $messages, array $options=[])
Definition: updateIsoDatabase.php:42
‪XliffDumper\formatCatalogue
‪formatCatalogue(MessageCatalogue $messages, string $domain, array $options=[])
Definition: updateIsoDatabase.php:52
‪$supportedLanguagesInTypo3
‪$supportedLanguagesInTypo3
Definition: updateIsoDatabase.php:106
‪$targetXliffDirectory
‪$targetXliffDirectory
Definition: updateIsoDatabase.php:99