| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Plugins\Intl\Commands; |
|
|
| use DateTimeZone; |
| use Piwik\Container\StaticContainer; |
| use Piwik\Development; |
| use Piwik\Filesystem; |
| use Piwik\Http; |
| use Piwik\Plugin\ConsoleCommand; |
| use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\EncodedEntities; |
| use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\UnnecassaryWhitespaces; |
| use Piwik\Plugins\LanguagesManager\TranslationWriter\Writer; |
|
|
| |
| |
| |
| |
| |
| class GenerateIntl extends ConsoleCommand |
| { |
| |
| |
| |
| public $CLDRVersion = "48.1.0"; |
|
|
| |
| |
| |
| public function isEnabled() |
| { |
| return Development::isEnabled(); |
| } |
|
|
| |
| |
| |
| protected function configure() |
| { |
| $this->setName('translations:generate-intl-data') |
| ->addOptionalValueOption('language', 'l', 'language that should be fetched') |
| ->addOptionalValueOption('cldr-version', '', 'CLDR version to use for update') |
| ->setDescription('Generates Intl-data for Piwik'); |
| } |
|
|
| protected function transformLangCode(string $langCode): string |
| { |
| if (substr_count($langCode, '-') == 1) { |
| $langCodeParts = explode('-', $langCode, 2); |
| return sprintf('%s-%s', $langCodeParts[0], strtoupper($langCodeParts[1])); |
| } |
| return $langCode; |
| } |
|
|
| protected function transform(?string $str): string |
| { |
| if (empty($str)) { |
| return ''; |
| } |
|
|
| preg_match_all("~^(.)(.*)$~u", $str, $arr); |
| return mb_strtoupper($arr[1][0]) . $arr[2][0]; |
| } |
|
|
| protected function doExecute(): int |
| { |
| $input = $this->getInput(); |
| $matomoLanguages = \Piwik\Plugins\LanguagesManager\API::getInstance()->getAvailableLanguages(); |
|
|
| if ($input->getOption('language')) { |
| $matomoLanguages = [$input->getOption('language')]; |
| } |
|
|
| if ($input->getOption('cldr-version')) { |
| $this->CLDRVersion = $input->getOption('cldr-version'); |
| } |
|
|
| $aliasesUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-core/supplemental/aliases.json'; |
| $aliasesData = Http::fetchRemoteFile(sprintf($aliasesUrl, $this->CLDRVersion)); |
| |
| $aliasesData = json_decode($aliasesData ?: '', true); |
| $aliasesData = $aliasesData['supplemental']['metadata']['alias']['languageAlias'] ?? []; |
|
|
| $this->checkCurrencies(); |
|
|
| foreach ($matomoLanguages as $langCode) { |
| if ($langCode === 'dev') { |
| continue; |
| } |
|
|
| $requestLangCode = $transformedLangCode = $this->transformLangCode($langCode); |
|
|
| if (array_key_exists($requestLangCode, $aliasesData)) { |
| $requestLangCode = (string)$aliasesData[$requestLangCode]['_replacement']; |
| } |
|
|
| |
| $localFixes = [ |
| 'pt' => 'pt-PT', |
| 'pt-br' => 'pt', |
| 'zh-cn' => 'zh-Hans', |
| 'zh-tw' => 'zh-Hant', |
| ]; |
|
|
| if (array_key_exists($langCode, $localFixes)) { |
| $requestLangCode = $localFixes[$langCode]; |
| } |
|
|
| setlocale(LC_ALL, $langCode); |
|
|
| $translations = []; |
|
|
| $this->fetchLanguageData($transformedLangCode, $requestLangCode, $translations); |
| $this->fetchTerritoryData($transformedLangCode, $requestLangCode, $translations); |
| $this->fetchCurrencyData($transformedLangCode, $requestLangCode, $translations); |
| $this->fetchCalendarData($transformedLangCode, $requestLangCode, $translations); |
| $this->fetchTimeZoneData($transformedLangCode, $requestLangCode, $translations); |
| $this->fetchLayoutDirection($transformedLangCode, $requestLangCode, $translations); |
| $this->fetchUnitData($transformedLangCode, $requestLangCode, $translations); |
| $this->fetchNumberFormattingData($transformedLangCode, $requestLangCode, $translations); |
| $this->fetchListingLayouts($transformedLangCode, $requestLangCode, $translations); |
|
|
| |
| if (empty($translations['Intl']['OriginalLanguageName']) && strpos($transformedLangCode, '-')) { |
| [$language, $territory] = explode('-', $transformedLangCode); |
|
|
| if (!empty($translations['Intl']['Language_' . $language])) { |
| $originalName = $this->transform($translations['Intl']['Language_' . $language]); |
|
|
| if (!empty($translations['Intl']['Country_' . $territory])) { |
| $originalName .= ' (' . $translations['Intl']['Country_' . $territory] . ')'; |
| } else { |
| $originalName .= ' (' . strtoupper($language) . ')'; |
| } |
|
|
| $translations['Intl']['OriginalLanguageName'] = $originalName; |
| } |
| } |
|
|
| ksort($translations['Intl']); |
|
|
| $translationWriter = new Writer($langCode, 'Intl'); |
| $translationWriter->setTranslations($translations); |
| $translationWriter->addFilter(new UnnecassaryWhitespaces()); |
| $translationWriter->addFilter(new EncodedEntities()); |
| $translationWriter->save(); |
| } |
|
|
| return self::SUCCESS; |
| } |
|
|
| protected function checkCurrencies(): void |
| { |
| $currencyDataUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-core/supplemental/currencyData.json'; |
|
|
| $currencyData = Http::fetchRemoteFile(sprintf($currencyDataUrl, $this->CLDRVersion)); |
| |
| $currencyData = json_decode($currencyData ?: '', true); |
| $currencyData = $currencyData['supplemental']['currencyData']['region'] ?? []; |
|
|
| $cldrCurrencies = []; |
| foreach ($currencyData as $region) { |
| foreach ($region as $regionCurrencies) { |
| foreach ($regionCurrencies as $currencyCode => $validity) { |
| if (!isset($validity['_to']) && !isset($validity['_tender'])) { |
| $cldrCurrencies[] = $currencyCode; |
| } |
| } |
| } |
| } |
|
|
| $file = Filesystem::getPathToPiwikRoot() . '/core/Intl/Data/Resources/currencies.php'; |
| $matomoCurrencies = array_keys(include $file); |
|
|
| $missing = array_diff($cldrCurrencies, $matomoCurrencies); |
| $additional = array_diff($matomoCurrencies, $cldrCurrencies); |
|
|
| if ($missing) { |
| $this->getOutput()->writeln('Warning: Currencies missing from ' . $file . ': ' . implode(', ', $missing)); |
| } |
| if ($additional) { |
| $this->getOutput()->writeln('Warning: Unknown currencies in ' . $file . ': ' . implode(', ', $additional)); |
| } |
| } |
|
|
| protected function getEnglishLanguageName(string $code, string $alternateCode): string |
| { |
| $languageDataUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-localenames-full/main/%s/languages.json'; |
|
|
| static $languageData = []; |
|
|
| try { |
| if (empty($languageData)) { |
| $languageData = Http::fetchRemoteFile(sprintf($languageDataUrl, $this->CLDRVersion, 'en')); |
| |
| $languageData = json_decode($languageData ?: '', true); |
| $languageData = $languageData['main']['en']['localeDisplayNames']['languages'] ?? []; |
| } |
|
|
| if (array_key_exists($code, $languageData) && $languageData[$code] != $code) { |
| return $this->transform($languageData[$code]); |
| } |
|
|
| if (array_key_exists($alternateCode, $languageData) && $languageData[$alternateCode] != $alternateCode) { |
| return $this->transform($languageData[$alternateCode]); |
| } |
|
|
| if (strpos($code, '-')) { |
| [$language, $territory] = explode('-', $code); |
|
|
| if (!array_key_exists($language, $languageData)) { |
| return ''; |
| } |
|
|
| $englishName = $this->transform($languageData[$language]); |
|
|
| $territoryDataUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-localenames-full/main/%s/territories.json'; |
|
|
| try { |
| $territoryData = Http::fetchRemoteFile(sprintf($territoryDataUrl, $this->CLDRVersion, 'en')); |
| |
| $territoryData = json_decode($territoryData ?: '', true); |
| $territoryData = $territoryData['main']['en']['localeDisplayNames']['territories'] ?? []; |
|
|
| if (array_key_exists($territory, $territoryData)) { |
| $englishName .= ' (' . $territoryData[$territory] . ')'; |
| } else { |
| $englishName .= ' (' . strtoupper($language) . ')'; |
| } |
| } catch (\Exception $e) { |
| $englishName .= ' (' . strtoupper($language) . ')'; |
| } |
|
|
| return $englishName; |
| } |
| } catch (\Exception $e) { |
| } |
|
|
| return ''; |
| } |
|
|
| |
| |
| |
| protected function fetchLanguageData(string $langCode, string $requestLangCode, array &$translations): void |
| { |
| $languageCodes = array_keys(StaticContainer::get('Piwik\Intl\Data\Provider\LanguageDataProvider')->getLanguageList()); |
|
|
| $languageDataUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-localenames-full/main/%s/languages.json'; |
|
|
| try { |
| $languageData = Http::fetchRemoteFile(sprintf($languageDataUrl, $this->CLDRVersion, $requestLangCode)); |
| |
| $languageData = json_decode($languageData ?: '', true); |
| $languageData = $languageData['main'][$requestLangCode]['localeDisplayNames']['languages'] ?? []; |
|
|
| if (empty($languageData)) { |
| throw new \Exception(); |
| } |
|
|
| foreach ($languageCodes as $code) { |
| if (!empty($languageData[$code]) && $languageData[$code] != $code) { |
| $translations['Intl']['Language_' . $code] = $this->transform($languageData[$code]); |
| } |
| } |
|
|
| if (array_key_exists($langCode, $languageData) && $languageData[$langCode] != $langCode && $langCode !== 'pt') { |
| |
| $translations['Intl']['OriginalLanguageName'] = $this->transform($languageData[$langCode]); |
| } elseif (array_key_exists($requestLangCode, $languageData) && $languageData[$requestLangCode] != $requestLangCode) { |
| $translations['Intl']['OriginalLanguageName'] = $this->transform($languageData[$requestLangCode]); |
| } |
| $translations['Intl']['EnglishLanguageName'] = $this->getEnglishLanguageName($langCode, $requestLangCode); |
|
|
| $this->getOutput()->writeln('Saved language data for ' . $langCode); |
| } catch (\Exception $e) { |
| $this->getOutput()->writeln('Unable to import language data for ' . $langCode); |
| } |
| } |
|
|
| |
| |
| |
| protected function fetchLayoutDirection(string $langCode, string $requestLangCode, array &$translations): void |
| { |
| $layoutDirectionUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-misc-full/main/%s/layout.json'; |
|
|
| try { |
| $layoutData = Http::fetchRemoteFile(sprintf($layoutDirectionUrl, $this->CLDRVersion, $requestLangCode)); |
| |
| $layoutData = json_decode($layoutData ?: '', true); |
| $layoutData = $layoutData['main'][$requestLangCode]['layout']['orientation'] ?? []; |
|
|
| if (empty($layoutData)) { |
| throw new \Exception(); |
| } |
|
|
| $translations['Intl']['LayoutDirection'] = 'ltr'; |
| if ($layoutData['characterOrder'] == 'right-to-left') { |
| $translations['Intl']['LayoutDirection'] = 'rtl'; |
| } |
|
|
| $this->getOutput()->writeln('Saved language data for ' . $langCode); |
| } catch (\Exception $e) { |
| $this->getOutput()->writeln('Unable to import language data for ' . $langCode); |
| } |
| } |
|
|
| |
| |
| |
| protected function fetchTerritoryData(string $langCode, string $requestLangCode, array &$translations): void |
| { |
| $territoryDataUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-localenames-full/main/%s/territories.json'; |
|
|
| $countryCodes = array_keys(StaticContainer::get('Piwik\Intl\Data\Provider\RegionDataProvider')->getCountryList()); |
| $countryCodes = array_map('strtoupper', $countryCodes); |
|
|
| $continentMapping = [ |
| "afr" => "002", |
| "amc" => "013", |
| "amn" => "003", |
| "ams" => "005", |
| "ant" => "AQ", |
| "asi" => "142", |
| "eur" => "150", |
| "oce" => "009", |
| ]; |
|
|
| try { |
| $territoryData = Http::fetchRemoteFile(sprintf($territoryDataUrl, $this->CLDRVersion, $requestLangCode)); |
| |
| $territoryData = json_decode($territoryData ?: '', true); |
| $territoryData = $territoryData['main'][$requestLangCode]['localeDisplayNames']['territories'] ?? []; |
|
|
| if (empty($territoryData)) { |
| throw new \Exception(); |
| } |
|
|
| foreach ($countryCodes as $code) { |
| if (!empty($territoryData[$code]) && $territoryData[$code] != $code) { |
| $translations['Intl']['Country_' . $code] = $this->transform($territoryData[$code]); |
| } |
| } |
|
|
| foreach ($continentMapping as $shortCode => $code) { |
| if (!empty($territoryData[$code]) && $territoryData[$code] != $code) { |
| $translations['Intl']['Continent_' . $shortCode] = $this->transform($territoryData[$code]); |
| } |
| } |
|
|
| $this->getOutput()->writeln('Saved territory data for ' . $langCode); |
| } catch (\Exception $e) { |
| $this->getOutput()->writeln('Unable to import territory data for ' . $langCode); |
| } |
| } |
|
|
| |
| |
| |
| protected function fetchCalendarData(string $langCode, string $requestLangCode, array &$translations): void |
| { |
| $calendarDataUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-dates-full/main/%s/ca-gregorian.json'; |
|
|
| try { |
| $calendarData = Http::fetchRemoteFile(sprintf($calendarDataUrl, $this->CLDRVersion, $requestLangCode)); |
| |
| $calendarData = json_decode($calendarData ?: '', true); |
| $calendarData = $calendarData['main'][$requestLangCode]['dates']['calendars']['gregorian'] ?? []; |
|
|
| if (empty($calendarData)) { |
| throw new \Exception(); |
| } |
|
|
| for ($i = 1; $i <= 12; $i++) { |
| $translations['Intl']['Month_Short_' . $i] = $calendarData['months']['format']['abbreviated'][$i]; |
| $translations['Intl']['Month_Long_' . $i] = $calendarData['months']['format']['wide'][$i]; |
| $translations['Intl']['Month_Short_StandAlone_' . $i] = $calendarData['months']['stand-alone']['abbreviated'][$i]; |
| $translations['Intl']['Month_Long_StandAlone_' . $i] = $calendarData['months']['stand-alone']['wide'][$i]; |
| } |
|
|
| $days = [ |
| 1 => 'mon', |
| 2 => 'tue', |
| 3 => 'wed', |
| 4 => 'thu', |
| 5 => 'fri', |
| 6 => 'sat', |
| 7 => 'sun', |
| ]; |
|
|
| foreach ($days as $nr => $day) { |
| $translations['Intl']['Day_Min_' . $nr] = $calendarData['days']['format']['short'][$day]; |
| $translations['Intl']['Day_Short_' . $nr] = $calendarData['days']['format']['abbreviated'][$day]; |
| $translations['Intl']['Day_Long_' . $nr] = $calendarData['days']['format']['wide'][$day]; |
| $translations['Intl']['Day_Min_StandAlone_' . $nr] = $calendarData['days']['stand-alone']['short'][$day]; |
| $translations['Intl']['Day_Short_StandAlone_' . $nr] = $calendarData['days']['stand-alone']['abbreviated'][$day]; |
| $translations['Intl']['Day_Long_StandAlone_' . $nr] = $calendarData['days']['stand-alone']['wide'][$day]; |
| } |
|
|
| $translations['Intl']['Time_AM'] = $calendarData['dayPeriods']['format']['wide']['am']; |
| $translations['Intl']['Time_PM'] = $calendarData['dayPeriods']['format']['wide']['pm']; |
| $translations['Intl']['Format_Time'] = '{time}'; |
| $translations['Intl']['Format_Time_12'] = $calendarData['dateTimeFormats']['availableFormats']['hms']; |
| $translations['Intl']['Format_Time_24'] = $calendarData['dateTimeFormats']['availableFormats']['Hms']; |
| $translations['Intl']['Format_Hour_12'] = $calendarData['dateTimeFormats']['availableFormats']['h']; |
| $translations['Intl']['Format_Hour_24'] = $calendarData['dateTimeFormats']['availableFormats']['H']; |
| $translations['Intl']['Format_Date_Long'] = $calendarData['dateFormats']['full']; |
| $translations['Intl']['Format_Date_Day_Month'] = $calendarData['dateTimeFormats']['availableFormats']['MMMEd']; |
| $translations['Intl']['Format_Date_Short'] = $calendarData['dateFormats']['medium']; |
| $translations['Intl']['Format_Month_Short'] = $calendarData['dateTimeFormats']['availableFormats']['yMMM']; |
| $translations['Intl']['Format_Month_Long'] = $this->transformDateFormat($calendarData['dateTimeFormats']['availableFormats']['yMMM'], ['MMM' => 'MMMM', 'LLL' => 'LLLL']); |
| if (isset($calendarData['dateTimeFormats']['availableFormats']['yMMMM'])) { |
| $translations['Intl']['Format_Month_Long'] = $calendarData['dateTimeFormats']['availableFormats']['yMMMM']; |
| } |
| $translations['Intl']['Format_Year'] = $calendarData['dateTimeFormats']['availableFormats']['y']; |
|
|
| $translations['Intl']['Format_DateTime_Long'] = $calendarData['dateFormats']['full'] . ' {time}'; |
| $translations['Intl']['Format_DateTime_Short'] = $calendarData['dateFormats']['medium'] . ' {time}'; |
|
|
| $translations['Intl']['Format_Interval_Long_D'] = $this->transformDateFormat($calendarData['dateTimeFormats']['intervalFormats']['yMMMd']['d'], ['MMMM' => 'MMM', 'LLLL' => 'LLL', 'MMM' => 'MMMM', 'LLL' => 'LLLL']); |
| $translations['Intl']['Format_Interval_Long_M'] = $this->transformDateFormat($calendarData['dateTimeFormats']['intervalFormats']['yMMMd']['M'], ['MMMM' => 'MMM', 'LLLL' => 'LLL', 'MMM' => 'MMMM', 'LLL' => 'LLLL']); |
| $translations['Intl']['Format_Interval_Long_Y'] = $this->transformDateFormat($calendarData['dateTimeFormats']['intervalFormats']['yMMMd']['y'], ['MMMM' => 'MMM', 'LLLL' => 'LLL', 'MMM' => 'MMMM', 'LLL' => 'LLLL']); |
|
|
| if (isset($calendarData['dateTimeFormats']['intervalFormats']['yMMMMd'])) { |
| $translations['Intl']['Format_Interval_Long_D'] = $calendarData['dateTimeFormats']['intervalFormats']['yMMMMd']['d']; |
| $translations['Intl']['Format_Interval_Long_M'] = $calendarData['dateTimeFormats']['intervalFormats']['yMMMMd']['M']; |
| $translations['Intl']['Format_Interval_Long_Y'] = $calendarData['dateTimeFormats']['intervalFormats']['yMMMMd']['y']; |
| } |
|
|
| $translations['Intl']['Format_Interval_Short_D'] = $calendarData['dateTimeFormats']['intervalFormats']['yMMMd']['d']; |
| $translations['Intl']['Format_Interval_Short_M'] = $calendarData['dateTimeFormats']['intervalFormats']['yMMMd']['M']; |
| $translations['Intl']['Format_Interval_Short_Y'] = $calendarData['dateTimeFormats']['intervalFormats']['yMMMd']['y']; |
|
|
| $this->getOutput()->writeln('Saved calendar data for ' . $langCode); |
| } catch (\Exception $e) { |
| $this->getOutput()->writeln('Unable to import calendar data for ' . $langCode); |
| } |
|
|
| $dateFieldsUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-dates-full/main/%s/dateFields.json'; |
|
|
| try { |
| $dateFieldData = Http::fetchRemoteFile(sprintf($dateFieldsUrl, $this->CLDRVersion, $requestLangCode)); |
| |
| $dateFieldData = json_decode($dateFieldData ?: '', true); |
| $dateFieldData = $dateFieldData['main'][$requestLangCode]['dates']['fields'] ?? []; |
|
|
| if (empty($dateFieldData)) { |
| throw new \Exception(); |
| } |
|
|
| $translations['Intl']['PeriodWeek'] = $dateFieldData['week']['displayName']; |
| $translations['Intl']['PeriodYear'] = $dateFieldData['year']['displayName']; |
| $translations['Intl']['PeriodDay'] = $dateFieldData['day']['displayName']; |
| $translations['Intl']['PeriodMonth'] = $dateFieldData['month']['displayName']; |
| $translations['Intl']['Year_Short'] = $dateFieldData['year-narrow']['displayName']; |
| $translations['Intl']['Today'] = $this->transform($dateFieldData['day']['relative-type-0']); |
| $translations['Intl']['Yesterday'] = $this->transform($dateFieldData['day']['relative-type--1']); |
|
|
| $this->getOutput()->writeln('Saved date fields for ' . $langCode); |
| } catch (\Exception $e) { |
| $this->getOutput()->writeln('Unable to import date fields for ' . $langCode); |
| } |
| } |
|
|
| |
| |
| |
| protected function fetchTimeZoneData(string $langCode, string $requestLangCode, array &$translations): void |
| { |
| $timeZoneDataUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-dates-full/main/%s/timeZoneNames.json'; |
|
|
| try { |
| $timeZoneData = Http::fetchRemoteFile(sprintf($timeZoneDataUrl, $this->CLDRVersion, $requestLangCode)); |
| |
| $timeZoneData = json_decode($timeZoneData ?: '', true); |
| $timeZoneData = $timeZoneData['main'][$requestLangCode]['dates']['timeZoneNames']['zone'] ?? []; |
|
|
| if (empty($timeZoneData)) { |
| throw new \Exception(); |
| } |
|
|
| $cities = []; |
| foreach ($timeZoneData as $key1 => $level1) { |
| foreach ($level1 as $key2 => $level2) { |
| if (isset($level2['exemplarCity'])) { |
| $level2 = [$level2]; |
| } |
| foreach ($level2 as $key3 => $level3) { |
| if (isset($level3['exemplarCity'])) { |
| $timezone = $key1 . '/' . $key2; |
| if ($key3) { |
| $timezone .= '/' . $key3; |
| } |
| $cities[$timezone] = $level3['exemplarCity']; |
| } |
| } |
| } |
| } |
|
|
| foreach ($cities as $timezone => $city) { |
| try { |
| $zone = new DateTimeZone($timezone); |
| } catch (\Exception $e) { |
| continue; |
| } |
| $location = $zone->getLocation(); |
| if (!isset($location['country_code'])) { |
| continue; |
| } |
| |
| $timezonesInCountry = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $location['country_code']); |
| if (count($timezonesInCountry) > 1) { |
| $translations['Intl']['Timezone_' . str_replace(['_', '/'], ['', '_'], $timezone)] = $city; |
| } |
| } |
|
|
| $this->getOutput()->writeln('Saved time zone data for ' . $langCode); |
| } catch (\Exception $e) { |
| $this->getOutput()->writeln('Unable to import time zone data for ' . $langCode); |
| } |
| } |
|
|
| |
| |
| |
| protected function transformDateFormat(?string $dateFormat, array $changes): string |
| { |
| return str_replace(array_keys($changes), array_values($changes), $dateFormat ?? ''); |
| } |
|
|
| |
| |
| |
| protected function fetchNumberFormattingData(string $langCode, string $requestLangCode, array &$translations): void |
| { |
| $unitsUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-numbers-full/main/%s/numbers.json'; |
|
|
| try { |
| $unitsData = Http::fetchRemoteFile(sprintf($unitsUrl, $this->CLDRVersion, $requestLangCode)); |
| |
| $unitsData = json_decode($unitsData ?: '', true); |
| $unitsData = $unitsData['main'][$requestLangCode]['numbers'] ?? []; |
|
|
| if (empty($unitsData)) { |
| throw new \Exception(); |
| } |
|
|
| $numberingSystem = $unitsData['defaultNumberingSystem']; |
|
|
| $translations['Intl']['NumberSymbolDecimal'] = $unitsData['symbols-numberSystem-' . $numberingSystem]['decimal']; |
| $translations['Intl']['NumberSymbolGroup'] = $unitsData['symbols-numberSystem-' . $numberingSystem]['group']; |
| $translations['Intl']['NumberSymbolPercent'] = $unitsData['symbols-numberSystem-' . $numberingSystem]['percentSign']; |
| $translations['Intl']['NumberSymbolPlus'] = $unitsData['symbols-numberSystem-' . $numberingSystem]['plusSign']; |
| $translations['Intl']['NumberSymbolMinus'] = $unitsData['symbols-numberSystem-' . $numberingSystem]['minusSign']; |
| $translations['Intl']['NumberFormatNumber'] = $unitsData['decimalFormats-numberSystem-' . $numberingSystem]['standard']; |
| $translations['Intl']['NumberFormatCurrency'] = $unitsData['currencyFormats-numberSystem-' . $numberingSystem]['standard']; |
| $translations['Intl']['NumberFormatPercent'] = $unitsData['percentFormats-numberSystem-' . $numberingSystem]['standard']; |
|
|
| for ($i = 1000; $i <= 1000000000000000000; $i *= 10) { |
| $numberCombatFormats = $unitsData['decimalFormats-numberSystem-' . $numberingSystem]['short']['decimalFormat'] ?? []; |
|
|
| if (!empty($numberCombatFormats)) { |
| $translations['Intl']['NumberFormatNumberCompact' . $i . 'One'] = $numberCombatFormats[$i . '-count-one'] ?? ''; |
| $translations['Intl']['NumberFormatNumberCompact' . $i . 'Other'] = $numberCombatFormats[$i . '-count-other'] ?? ''; |
| } |
|
|
| $currencyCombatFormats = $unitsData['currencyFormats-numberSystem-' . $numberingSystem]['short']['standard'] ?? []; |
|
|
| if (!empty($currencyCombatFormats)) { |
| $translations['Intl']['NumberFormatCurrencyCompact' . $i . 'One'] = $currencyCombatFormats[$i . '-count-one'] ?? ''; |
| $translations['Intl']['NumberFormatCurrencyCompact' . $i . 'Other'] = $currencyCombatFormats[$i . '-count-other'] ?? ''; |
| } |
| } |
|
|
| $this->getOutput()->writeln('Saved number formatting data for ' . $langCode); |
| } catch (\Exception $e) { |
| $this->getOutput()->writeln('Unable to import number formatting data for ' . $langCode); |
| } |
| } |
|
|
| |
| |
| |
| protected function fetchUnitData(string $langCode, string $requestLangCode, array &$translations): void |
| { |
| $unitsUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-units-full/main/%s/units.json'; |
|
|
| try { |
| $unitsData = Http::fetchRemoteFile(sprintf($unitsUrl, $this->CLDRVersion, $requestLangCode)); |
| |
| $unitsData = json_decode($unitsData ?: '', true); |
| $unitsData = $unitsData['main'][$requestLangCode]['units'] ?? []; |
|
|
| if (empty($unitsData)) { |
| throw new \Exception(); |
| } |
|
|
| $translations['Intl']['NSeconds'] = $this->replacePlaceHolder($unitsData['long']['duration-second']['unitPattern-count-other']); |
| $translations['Intl']['NSecondsShort'] = $this->replacePlaceHolder($unitsData['narrow']['duration-second']['unitPattern-count-other']); |
| $translations['Intl']['Seconds'] = $unitsData['long']['duration-second']['displayName']; |
|
|
| $translations['Intl']['NMinutes'] = $this->replacePlaceHolder($unitsData['long']['duration-minute']['unitPattern-count-other']); |
|
|
| if (isset($unitsData['long']['duration-minute']['unitPattern-count-one'])) { |
| $translations['Intl']['OneMinute'] = $this->replacePlaceHolder($unitsData['long']['duration-minute']['unitPattern-count-one'], '1'); |
| } else { |
| $translations['Intl']['OneMinute'] = $this->replacePlaceHolder($unitsData['long']['duration-minute']['unitPattern-count-other'], '1'); |
| } |
|
|
| if (isset($unitsData['short']['duration-minute']['unitPattern-count-one'])) { |
| $translations['Intl']['OneMinuteShort'] = $this->replacePlaceHolder($unitsData['short']['duration-minute']['unitPattern-count-one'], '1'); |
| } else { |
| $translations['Intl']['OneMinuteShort'] = $this->replacePlaceHolder($unitsData['short']['duration-minute']['unitPattern-count-other'], '1'); |
| } |
|
|
| $translations['Intl']['NMinutesShort'] = $this->replacePlaceHolder($unitsData['short']['duration-minute']['unitPattern-count-other']); |
|
|
| $translations['Intl']['Minutes'] = $unitsData['long']['duration-minute']['displayName']; |
|
|
| $translations['Intl']['Hours'] = $unitsData['long']['duration-hour']['displayName']; |
| $translations['Intl']['NHoursShort'] = $this->replacePlaceHolder($unitsData['narrow']['duration-hour']['unitPattern-count-other']); |
|
|
| $translations['Intl']['NDays'] = $this->replacePlaceHolder($unitsData['long']['duration-day']['unitPattern-count-other']); |
|
|
| if (isset($unitsData['short']['duration-day']['unitPattern-count-one'])) { |
| $translations['Intl']['OneDay'] = $this->replacePlaceHolder($unitsData['long']['duration-day']['unitPattern-count-one'], '1'); |
| } else { |
| $translations['Intl']['OneDay'] = $this->replacePlaceHolder($unitsData['long']['duration-day']['unitPattern-count-other'], '1'); |
| } |
|
|
| $translations['Intl']['PeriodWeeks'] = $unitsData['long']['duration-week']['displayName']; |
| $translations['Intl']['PeriodYears'] = $unitsData['long']['duration-year']['displayName']; |
| $translations['Intl']['PeriodDays'] = $unitsData['long']['duration-day']['displayName']; |
| $translations['Intl']['PeriodMonths'] = $unitsData['long']['duration-month']['displayName']; |
|
|
|
|
| $this->getOutput()->writeln('Saved unit data for ' . $langCode); |
| } catch (\Exception $e) { |
| $this->getOutput()->writeln('Unable to import unit data for ' . $langCode); |
| } |
| } |
|
|
| |
| |
| |
| protected function fetchCurrencyData(string $langCode, string $requestLangCode, array &$translations): void |
| { |
| $currenciesUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-numbers-full/main/%s/currencies.json'; |
|
|
| try { |
| $currencyData = Http::fetchRemoteFile(sprintf($currenciesUrl, $this->CLDRVersion, $requestLangCode)); |
| |
| $currencyData = json_decode($currencyData ?: '', true); |
| $currencyData = $currencyData['main'][$requestLangCode]['numbers']['currencies'] ?? []; |
|
|
| if (empty($currencyData)) { |
| throw new \Exception(); |
| } |
|
|
| $dataProvider = StaticContainer::get('Piwik\Intl\Data\Provider\CurrencyDataProvider'); |
| foreach ($dataProvider->getCurrencyList() as $code => $currency) { |
| if (isset($currencyData[$code]['displayName'])) { |
| $translations['Intl']['Currency_' . $code] = $this->transform($currencyData[$code]['displayName']); |
| } else { |
| $translations['Intl']['Currency_' . $code] = $currency[1]; |
| } |
| if (isset($currencyData[$code]['symbol'])) { |
| $translations['Intl']['CurrencySymbol_' . $code] = $currencyData[$code]['symbol']; |
| } else { |
| $translations['Intl']['CurrencySymbol_' . $code] = $currency[0]; |
| } |
| } |
|
|
| $this->getOutput()->writeln('Saved currency data for ' . $langCode); |
| } catch (\Exception $e) { |
| $this->getOutput()->writeln('Unable to import currency data for ' . $langCode); |
| } |
| } |
|
|
| |
| |
| |
| protected function fetchListingLayouts(string $langCode, string $requestLangCode, array &$translations): void |
| { |
| $listingLayoutsUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-misc-full/main/%s/listPatterns.json'; |
|
|
| try { |
| $listingLayouts = Http::fetchRemoteFile(sprintf($listingLayoutsUrl, $this->CLDRVersion, $requestLangCode)); |
| |
| $listingLayouts = json_decode($listingLayouts ?: '', true); |
| $listingLayouts = $listingLayouts['main'][$requestLangCode]['listPatterns'] ?? []; |
|
|
| if (empty($listingLayouts)) { |
| throw new \Exception(); |
| } |
|
|
| if (isset($listingLayouts['listPattern-type-standard'])) { |
| $translations['Intl']['ListPatternAndStart'] = $listingLayouts['listPattern-type-standard']['start']; |
| $translations['Intl']['ListPatternAndMiddle'] = $listingLayouts['listPattern-type-standard']['middle']; |
| $translations['Intl']['ListPatternAndEnd'] = $listingLayouts['listPattern-type-standard']['end']; |
| $translations['Intl']['ListPatternAnd2'] = $listingLayouts['listPattern-type-standard']['2']; |
| } |
|
|
| if (isset($listingLayouts['listPattern-type-or'])) { |
| $translations['Intl']['ListPatternOrStart'] = $listingLayouts['listPattern-type-or']['start']; |
| $translations['Intl']['ListPatternOrMiddle'] = $listingLayouts['listPattern-type-or']['middle']; |
| $translations['Intl']['ListPatternOrEnd'] = $listingLayouts['listPattern-type-or']['end']; |
| $translations['Intl']['ListPatternOr2'] = $listingLayouts['listPattern-type-or']['2']; |
| } |
|
|
| $this->getOutput()->writeln('Saved listing layout data for ' . $langCode); |
| } catch (\Exception $e) { |
| $this->getOutput()->writeln('Unable to import listing layout data for ' . $langCode); |
| } |
| } |
|
|
| protected function replacePlaceHolder(string $string, string $replacement = '%s'): string |
| { |
| return str_replace('{0}', $replacement, $string); |
| } |
| } |
|
|