[ Mini Kiebo ]
Server: Windows NT DESKTOP-5B8S0D4 6.2 build 9200 (Windows 8 Professional Edition) i586
Path:
D:
/
Backup
/
05122024
/
htdocs
/
jurnal-kesmas
/
baru
/
lib
/
pkp
/
classes
/
i18n
/
[
Home
]
File: LocaleMetadata.php
<?php declare(strict_types=1); /** * @defgroup i18n I18N * Implements localization concerns such as locale files, time zones, and country lists. */ /** * @file classes/i18n/LocaleMetadata.php * * Copyright (c) 2014-2021 Simon Fraser University * Copyright (c) 2000-2021 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class LocaleMetadata * * @ingroup i18n * * @brief Holds metadata about a system locale */ namespace PKP\i18n; use DomainException; use Exception; use PKP\core\ExportableTrait; use PKP\core\PKPString; use PKP\facades\Locale; use PKP\i18n\interfaces\LocaleInterface; use Sokil\IsoCodes\Database\Languages\Language; class LocaleMetadata { use ExportableTrait; /** * The following constants define how the locale information will be presented * * LANGUAGE_LOCALE_WITHOUT : The locale will be presented in the current selected language * So, if English and French is available and user selected locale is French, it will be * shown as Français | Anglais * * LANGUAGE_LOCALE_WITH : The locale will be presented in current selected language along * with each locale's own translated name . So, if English and French is available and user * selected locale is French, it will be shown as Français/French | Anglais/English * * LANGUAGE_LOCALE_ONLY : The locale will be presented only in each locale's translated * name . So, if English and French is available and user * selected locale is French, it will be shown as Français | English */ public const LANGUAGE_LOCALE_WITHOUT = 1; public const LANGUAGE_LOCALE_WITH = 2; public const LANGUAGE_LOCALE_ONLY = 3; private ?object $_parsedLocale = null; /** * Constructor */ public function __construct( /** Locale identification */ public ?string $locale = null ) { } /** * Get the language locale conversion status * */ public static function getLanguageLocaleStatuses(): array { return [ self::LANGUAGE_LOCALE_WITHOUT, self::LANGUAGE_LOCALE_WITH, self::LANGUAGE_LOCALE_ONLY ]; } /** * Retrieves the display name * * @param string $locale The locale code * @param bool $withCountry Whether to append the country name to language * @param int $langLocaleStatus The language locale conversion value specified by const LocaleMetadata::LANGUAGE_LOCALE_* * * @return string The fully qualified locale with/without own translated locale and with/without country name */ public function getDisplayName(?string $locale = null, bool $withCountry = false, int $langLocaleStatus = self::LANGUAGE_LOCALE_WITHOUT): string { if (!in_array($langLocaleStatus, static::getLanguageLocaleStatuses())) { throw new Exception( sprintf( 'Invalid language locale conversion status %s given, must be among [%s]', $langLocaleStatus, implode(',', static::getLanguageLocaleStatuses()) ) ); } $name = PKPString::regexp_replace( '/\s*\([^)]*\)\s*/', '', PKPString::ucfirst( $this ->_getLanguage( $langLocaleStatus === self::LANGUAGE_LOCALE_ONLY ? $this->locale : $locale, $langLocaleStatus === self::LANGUAGE_LOCALE_WITH ) ->getLocalName() ) ); if ($langLocaleStatus === self::LANGUAGE_LOCALE_WITH) { // Get the translated language name in language's own locale $nameInLangLocale = PKPString::regexp_replace( '/\s*\([^)]*\)\s*/', '', PKPString::ucfirst($this->_getLanguage($this->locale)->getLocalName()) ); $name = __( 'common.withForwardSlash', [ 'item' => $name, 'afterSlash' => $nameInLangLocale, ] ); } if (!$withCountry) { return $name; } $country = $this->getCountry($locale); if (!$country) { return $name; } if ($langLocaleStatus !== self::LANGUAGE_LOCALE_WITHOUT) { $localizedCountryName = $this->getCountry($this->locale); if ($langLocaleStatus === self::LANGUAGE_LOCALE_ONLY) { $country = $localizedCountryName; } else { if (strcmp($localizedCountryName, $country) !== 0) { $country = __( 'common.withForwardSlash', [ 'item' => $country, 'afterSlash' => $localizedCountryName ] ); } } } return __( 'common.withParenthesis', [ 'item' => $name, 'inParenthesis' => $country, ] ); } /** * Retrieves the language name */ public function getLanguage(?string $locale = null): string { return $this->_getLanguage($locale)->getLocalName(); } /** * Retrieves the country name */ public function getCountry(?string $locale = null): ?string { return $this->_parse()->country ? Locale::getCountries($locale)->getByAlpha2($this->_parse()->country)?->getLocalName() : null; } /** * Retrieves the script name */ public function getScript(?string $locale = null): ?string { $script = ucfirst($this->_parse()->script); return $this->_parse()->script ? Locale::getScripts($locale)->getByAlpha4($script)->getLocalName() : null; } /** * Whether the locale expects text on the right-to-left format */ public function isRightToLeft(): bool { $locale = $this->_parse(); $language = strtolower($locale->language ?? ''); $script = strtolower($locale->script ?? ''); $rightToLeftLanguages = array_fill_keys(['ar', 'dv', 'fa', 'he', 'ku', 'nqo', 'prs', 'ps', 'sd', 'syr', 'ug', 'ur', 'yi'], true); $languageScriptExceptions = ['sd-deva' => false, 'tzm-arab' => true, 'pa-arab' => true]; return $languageScriptExceptions["{$language}-{$script}"] ?? $rightToLeftLanguages[$language] ?? $languageScriptExceptions[$this->getIsoAlpha3() . "-{$script}"] ?? $rightToLeftLanguages[$this->getIsoAlpha3()] ?? false; } /** * Compares two locales and retrieves the completeness ratio (source locale keys which are present in the reference) * If a locale isn't supplied, LocaleInterface::DEFAULT_LOCALE will be used as reference */ public function getCompletenessRatio(string $referenceLocale = null): float { $destiny = Locale::getBundle($referenceLocale ?? LocaleInterface::DEFAULT_LOCALE)->getTranslator()->getEntries(); $source = Locale::getBundle($this->locale, false)->getTranslator()->getEntries(); $intersection = array_intersect_key($source, $destiny); return min(1, count($intersection) / max(1, count($destiny))); } /** * Retrieves whether the locale can be considered complete respecting a threshold level of completeness */ public function isComplete(float $minimumThreshold = 0.9, ?string $referenceLocale = null): bool { return $this->getCompletenessRatio($referenceLocale) >= $minimumThreshold; } /** * Retrieves the ISO639-1 representation */ public function getIsoAlpha2(): string { return $this->_getLanguage()->getAlpha2(); } /** * Retrieves the ISO639-3 representation */ public function getIsoAlpha3(): string { return $this->_getLanguage()->getAlpha3(); } /** * Retrieves the language */ private function _getLanguage(?string $locale = null, bool $fromCache = true): ?Language { return Locale::getLanguages($locale, $fromCache)->getByAlpha2($this->_parse()->language); } /** * Parses the locale string and retrieve its pieces */ private function _parse(): object { if (isset($this->_parsedLocale)) { return $this->_parsedLocale; } if (!preg_match(LocaleInterface::LOCALE_EXPRESSION, $this->locale, $matches)) { throw new DomainException("Invalid locale \"{$this->locale}\""); } return $this->_parsedLocale = (object) [ 'language' => $matches['language'], 'country' => $matches['country'] ?? null, // Updates our script definitions to match the ISO 15924 'script' => isset($matches['script']) ? str_replace(['cyrillic', 'latin'], ['latn', 'cyrl'], strtolower($matches['script'])) : null ]; } }