From d6b67d469a8767d88d5745b11b711c644e340ffc Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Fri, 12 Oct 2018 21:48:56 +0200 Subject: [PATCH] [Intl] Simplify API --- UPGRADE-4.3.md | 9 + UPGRADE-5.0.md | 9 + .../Form/Extension/Core/Type/CountryType.php | 6 +- .../Form/Extension/Core/Type/CurrencyType.php | 6 +- .../Form/Extension/Core/Type/LanguageType.php | 6 +- .../Form/Extension/Core/Type/LocaleType.php | 6 +- src/Symfony/Component/Form/composer.json | 3 +- src/Symfony/Component/Intl/CHANGELOG.md | 9 + src/Symfony/Component/Intl/Currencies.php | 117 +++ .../Data/Provider/CurrencyDataProvider.php | 2 +- .../Data/Provider/LanguageDataProvider.php | 2 +- .../Intl/Data/Provider/LocaleDataProvider.php | 2 +- .../Intl/Data/Provider/RegionDataProvider.php | 2 +- .../Intl/Data/Provider/ScriptDataProvider.php | 2 +- src/Symfony/Component/Intl/Intl.php | 22 +- src/Symfony/Component/Intl/Languages.php | 79 ++ src/Symfony/Component/Intl/Locales.php | 68 ++ .../Intl/NumberFormatter/NumberFormatter.php | 10 +- src/Symfony/Component/Intl/Regions.php | 60 ++ src/Symfony/Component/Intl/ResourceBundle.php | 76 ++ .../Intl/ResourceBundle/CurrencyBundle.php | 2 +- .../CurrencyBundleInterface.php | 2 + .../Intl/ResourceBundle/LanguageBundle.php | 2 +- .../LanguageBundleInterface.php | 2 + .../Intl/ResourceBundle/LocaleBundle.php | 2 +- .../ResourceBundle/LocaleBundleInterface.php | 2 + .../Intl/ResourceBundle/RegionBundle.php | 2 +- .../ResourceBundle/RegionBundleInterface.php | 2 + .../ResourceBundleInterface.php | 2 + src/Symfony/Component/Intl/Scripts.php | 60 ++ .../Component/Intl/Tests/CurrenciesTest.php | 789 +++++++++++++++ .../AbstractCurrencyDataProviderTest.php | 2 + .../Provider/AbstractDataProviderTest.php | 2 + .../AbstractLanguageDataProviderTest.php | 2 + .../AbstractLocaleDataProviderTest.php | 2 + .../AbstractRegionDataProviderTest.php | 2 + .../AbstractScriptDataProviderTest.php | 1 + .../Json/JsonCurrencyDataProviderTest.php | 1 + .../Json/JsonLanguageDataProviderTest.php | 1 + .../Json/JsonLocaleDataProviderTest.php | 1 + .../Json/JsonRegionDataProviderTest.php | 1 + .../Json/JsonScriptDataProviderTest.php | 1 + src/Symfony/Component/Intl/Tests/IntlTest.php | 13 + .../Component/Intl/Tests/LanguagesTest.php | 918 ++++++++++++++++++ .../Component/Intl/Tests/LocalesTest.php | 87 ++ .../Component/Intl/Tests/RegionsTest.php | 346 +++++++ .../Intl/Tests/ResourceBundleTestCase.php | 751 ++++++++++++++ .../Component/Intl/Tests/ScriptsTest.php | 277 ++++++ .../Component/Validator/Constraints/Bic.php | 4 +- .../Validator/Constraints/BicValidator.php | 6 +- .../Validator/Constraints/Country.php | 4 +- .../Constraints/CountryValidator.php | 7 +- .../Validator/Constraints/Currency.php | 4 +- .../Constraints/CurrencyValidator.php | 7 +- .../Validator/Constraints/Language.php | 4 +- .../Constraints/LanguageValidator.php | 7 +- .../Validator/Constraints/Locale.php | 4 +- .../Validator/Constraints/LocaleValidator.php | 5 +- src/Symfony/Component/Validator/composer.json | 4 +- 59 files changed, 3767 insertions(+), 60 deletions(-) create mode 100644 src/Symfony/Component/Intl/Currencies.php create mode 100644 src/Symfony/Component/Intl/Languages.php create mode 100644 src/Symfony/Component/Intl/Locales.php create mode 100644 src/Symfony/Component/Intl/Regions.php create mode 100644 src/Symfony/Component/Intl/ResourceBundle.php create mode 100644 src/Symfony/Component/Intl/Scripts.php create mode 100644 src/Symfony/Component/Intl/Tests/CurrenciesTest.php create mode 100644 src/Symfony/Component/Intl/Tests/LanguagesTest.php create mode 100644 src/Symfony/Component/Intl/Tests/LocalesTest.php create mode 100644 src/Symfony/Component/Intl/Tests/RegionsTest.php create mode 100644 src/Symfony/Component/Intl/Tests/ResourceBundleTestCase.php create mode 100644 src/Symfony/Component/Intl/Tests/ScriptsTest.php diff --git a/UPGRADE-4.3.md b/UPGRADE-4.3.md index 7442600260a8c..d0bd5cefe5ea4 100644 --- a/UPGRADE-4.3.md +++ b/UPGRADE-4.3.md @@ -94,6 +94,15 @@ HttpKernel * Renamed `PostResponseEvent` to `TerminateEvent` * Deprecated `TranslatorListener` in favor of `LocaleAwareListener` +Intl +---- + + * Deprecated `ResourceBundle` namespace + * Deprecated `Intl::getCurrencyBundle()`, use `Currencies` instead + * Deprecated `Intl::getLanguageBundle()`, use `Languages` or `Scripts` instead + * Deprecated `Intl::getLocaleBundle()`, use `Locales` instead + * Deprecated `Intl::getRegionBundle()`, use `Regions` instead + Messenger --------- diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index b163e76678286..e8c479c6bc332 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -237,6 +237,15 @@ HttpKernel * Removed `PostResponseEvent`, use `TerminateEvent` instead * Removed `TranslatorListener` in favor of `LocaleAwareListener` +Intl +---- + + * Removed `ResourceBundle` namespace + * Removed `Intl::getLanguageBundle()`, use `Languages` or `Scripts` instead + * Removed `Intl::getCurrencyBundle()`, use `Currencies` instead + * Removed `Intl::getLocaleBundle()`, use `Locales` instead + * Removed `Intl::getRegionBundle()`, use `Regions` instead + Messenger --------- diff --git a/src/Symfony/Component/Form/Extension/Core/Type/CountryType.php b/src/Symfony/Component/Form/Extension/Core/Type/CountryType.php index 2373dee5ff908..ff50c2fb00fef 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/CountryType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/CountryType.php @@ -15,7 +15,7 @@ use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Regions; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -44,7 +44,7 @@ public function configureOptions(OptionsResolver $resolver) $choiceTranslationLocale = $options['choice_translation_locale']; return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) { - return array_flip(Intl::getRegionBundle()->getCountryNames($choiceTranslationLocale)); + return array_flip(Regions::getNames($choiceTranslationLocale)); }); }, 'choice_translation_domain' => false, @@ -83,7 +83,7 @@ public function loadChoiceList($value = null) return $this->choiceList; } - return $this->choiceList = new ArrayChoiceList(array_flip(Intl::getRegionBundle()->getCountryNames()), $value); + return $this->choiceList = new ArrayChoiceList(array_flip(Regions::getNames()), $value); } /** diff --git a/src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php b/src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php index 134d568e4d174..486bdc7b20206 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php @@ -15,7 +15,7 @@ use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Currencies; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -44,7 +44,7 @@ public function configureOptions(OptionsResolver $resolver) $choiceTranslationLocale = $options['choice_translation_locale']; return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) { - return array_flip(Intl::getCurrencyBundle()->getCurrencyNames($choiceTranslationLocale)); + return array_flip(Currencies::getNames($choiceTranslationLocale)); }); }, 'choice_translation_domain' => false, @@ -83,7 +83,7 @@ public function loadChoiceList($value = null) return $this->choiceList; } - return $this->choiceList = new ArrayChoiceList(array_flip(Intl::getCurrencyBundle()->getCurrencyNames()), $value); + return $this->choiceList = new ArrayChoiceList(array_flip(Currencies::getNames()), $value); } /** diff --git a/src/Symfony/Component/Form/Extension/Core/Type/LanguageType.php b/src/Symfony/Component/Form/Extension/Core/Type/LanguageType.php index 88761598ab84b..4a0cbe1f8f459 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/LanguageType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/LanguageType.php @@ -15,7 +15,7 @@ use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Languages; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -44,7 +44,7 @@ public function configureOptions(OptionsResolver $resolver) $choiceTranslationLocale = $options['choice_translation_locale']; return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) { - return array_flip(Intl::getLanguageBundle()->getLanguageNames($choiceTranslationLocale)); + return array_flip(Languages::getNames($choiceTranslationLocale)); }); }, 'choice_translation_domain' => false, @@ -83,7 +83,7 @@ public function loadChoiceList($value = null) return $this->choiceList; } - return $this->choiceList = new ArrayChoiceList(array_flip(Intl::getLanguageBundle()->getLanguageNames()), $value); + return $this->choiceList = new ArrayChoiceList(array_flip(Languages::getNames()), $value); } /** diff --git a/src/Symfony/Component/Form/Extension/Core/Type/LocaleType.php b/src/Symfony/Component/Form/Extension/Core/Type/LocaleType.php index 853f98a928c25..41e016df1008b 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/LocaleType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/LocaleType.php @@ -15,7 +15,7 @@ use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Locales; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -44,7 +44,7 @@ public function configureOptions(OptionsResolver $resolver) $choiceTranslationLocale = $options['choice_translation_locale']; return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) { - return array_flip(Intl::getLocaleBundle()->getLocaleNames($choiceTranslationLocale)); + return array_flip(Locales::getNames($choiceTranslationLocale)); }); }, 'choice_translation_domain' => false, @@ -83,7 +83,7 @@ public function loadChoiceList($value = null) return $this->choiceList; } - return $this->choiceList = new ArrayChoiceList(array_flip(Intl::getLocaleBundle()->getLocaleNames()), $value); + return $this->choiceList = new ArrayChoiceList(array_flip(Locales::getNames()), $value); } /** diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 6de2563a7bb09..d448e77e5a7fe 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^7.1.3", "symfony/event-dispatcher": "^4.3", - "symfony/intl": "~3.4|~4.0", + "symfony/intl": "^4.3", "symfony/options-resolver": "~4.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", @@ -43,6 +43,7 @@ "symfony/doctrine-bridge": "<3.4", "symfony/framework-bundle": "<3.4", "symfony/http-kernel": "<4.3", + "symfony/intl": "<4.3", "symfony/translation": "<4.2", "symfony/twig-bridge": "<3.4.5|<4.0.5,>=4.0" }, diff --git a/src/Symfony/Component/Intl/CHANGELOG.md b/src/Symfony/Component/Intl/CHANGELOG.md index 4a61ee7178fab..7c8d46745533d 100644 --- a/src/Symfony/Component/Intl/CHANGELOG.md +++ b/src/Symfony/Component/Intl/CHANGELOG.md @@ -1,6 +1,15 @@ CHANGELOG ========= +4.3.0 +----- + + * deprecated `ResourceBundle` namespace + * added `Currencies` in favor of `Intl::getCurrencyBundle()` + * added `Languages` and `Scripts` in favor of `Intl::getLanguageBundle()` + * added `Locales` in favor of `Intl::getLocaleBundle()` + * added `Regions` in favor of `Intl::getRegionBundle()` + 4.2.0 ----- diff --git a/src/Symfony/Component/Intl/Currencies.php b/src/Symfony/Component/Intl/Currencies.php new file mode 100644 index 0000000000000..5d6a4b06cce63 --- /dev/null +++ b/src/Symfony/Component/Intl/Currencies.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl; + +use Symfony\Component\Intl\Exception\MissingResourceException; + +/** + * Gives access to currency-related ICU data. + * + * @author Bernhard Schussek + * @author Roland Franssen + */ +final class Currencies extends ResourceBundle +{ + private const INDEX_SYMBOL = 0; + private const INDEX_NAME = 1; + private const INDEX_FRACTION_DIGITS = 0; + private const INDEX_ROUNDING_INCREMENT = 1; + + /** + * @return string[] + */ + public static function getCurrencyCodes(): array + { + return self::readEntry(['Currencies'], 'meta'); + } + + public static function exists(string $currency): bool + { + try { + self::readEntry(['Names', $currency, self::INDEX_NAME]); + + return true; + } catch (MissingResourceException $e) { + return false; + } + } + + public static function getName(string $currency, string $displayLocale = null): string + { + return self::readEntry(['Names', $currency, self::INDEX_NAME], $displayLocale); + } + + /** + * @return string[] + */ + public static function getNames(string $displayLocale = null): array + { + // ==================================================================== + // For reference: It is NOT possible to return names indexed by + // numeric code here, because some numeric codes map to multiple + // 3-letter codes (e.g. 32 => "ARA", "ARP", "ARS") + // ==================================================================== + + $names = self::readEntry(['Names'], $displayLocale); + + if ($names instanceof \Traversable) { + $names = iterator_to_array($names); + } + + array_walk($names, function (&$value) { + $value = $value[self::INDEX_NAME]; + }); + + return self::asort($names, $displayLocale); + } + + public static function getSymbol(string $currency, string $displayLocale = null): string + { + return self::readEntry(['Names', $currency, self::INDEX_SYMBOL], $displayLocale); + } + + public static function getFractionDigits(string $currency): int + { + try { + return self::readEntry(['Meta', $currency, self::INDEX_FRACTION_DIGITS], 'meta'); + } catch (MissingResourceException $e) { + return self::readEntry(['Meta', 'DEFAULT', self::INDEX_FRACTION_DIGITS], 'meta'); + } + } + + /** + * @return float|int + */ + public static function getRoundingIncrement(string $currency) + { + try { + return self::readEntry(['Meta', $currency, self::INDEX_ROUNDING_INCREMENT], 'meta'); + } catch (MissingResourceException $e) { + return self::readEntry(['Meta', 'DEFAULT', self::INDEX_ROUNDING_INCREMENT], 'meta'); + } + } + + public static function getNumericCode(string $currency): int + { + return self::readEntry(['Alpha3ToNumeric', $currency], 'meta'); + } + + public static function forNumericCode(int $numericCode): array + { + return self::readEntry(['NumericToAlpha3', (string) $numericCode], 'meta'); + } + + protected static function getPath(): string + { + return Intl::getDataDirectory().'/'.Intl::CURRENCY_DIR; + } +} diff --git a/src/Symfony/Component/Intl/Data/Provider/CurrencyDataProvider.php b/src/Symfony/Component/Intl/Data/Provider/CurrencyDataProvider.php index 61814dfda3058..d4ee9af69b206 100644 --- a/src/Symfony/Component/Intl/Data/Provider/CurrencyDataProvider.php +++ b/src/Symfony/Component/Intl/Data/Provider/CurrencyDataProvider.php @@ -20,7 +20,7 @@ * * @author Bernhard Schussek * - * @internal + * @internal to be removed in 5.0. */ class CurrencyDataProvider { diff --git a/src/Symfony/Component/Intl/Data/Provider/LanguageDataProvider.php b/src/Symfony/Component/Intl/Data/Provider/LanguageDataProvider.php index 60a364b6447b0..b507f25b8f0d0 100644 --- a/src/Symfony/Component/Intl/Data/Provider/LanguageDataProvider.php +++ b/src/Symfony/Component/Intl/Data/Provider/LanguageDataProvider.php @@ -19,7 +19,7 @@ * * @author Bernhard Schussek * - * @internal + * @internal to be removed in 5.0. */ class LanguageDataProvider { diff --git a/src/Symfony/Component/Intl/Data/Provider/LocaleDataProvider.php b/src/Symfony/Component/Intl/Data/Provider/LocaleDataProvider.php index f42be225bcc5b..216ede8810f00 100644 --- a/src/Symfony/Component/Intl/Data/Provider/LocaleDataProvider.php +++ b/src/Symfony/Component/Intl/Data/Provider/LocaleDataProvider.php @@ -19,7 +19,7 @@ * * @author Bernhard Schussek * - * @internal + * @internal to be removed in 5.0. */ class LocaleDataProvider { diff --git a/src/Symfony/Component/Intl/Data/Provider/RegionDataProvider.php b/src/Symfony/Component/Intl/Data/Provider/RegionDataProvider.php index f45cae16a1f18..bf6a634aa200a 100644 --- a/src/Symfony/Component/Intl/Data/Provider/RegionDataProvider.php +++ b/src/Symfony/Component/Intl/Data/Provider/RegionDataProvider.php @@ -19,7 +19,7 @@ * * @author Bernhard Schussek * - * @internal + * @internal to be removed in 5.0. */ class RegionDataProvider { diff --git a/src/Symfony/Component/Intl/Data/Provider/ScriptDataProvider.php b/src/Symfony/Component/Intl/Data/Provider/ScriptDataProvider.php index 43651cae591d0..9f1ed1711f186 100644 --- a/src/Symfony/Component/Intl/Data/Provider/ScriptDataProvider.php +++ b/src/Symfony/Component/Intl/Data/Provider/ScriptDataProvider.php @@ -19,7 +19,7 @@ * * @author Bernhard Schussek * - * @internal + * @internal to be removed in 5.0. */ class ScriptDataProvider { diff --git a/src/Symfony/Component/Intl/Intl.php b/src/Symfony/Component/Intl/Intl.php index 70fc55697a841..7d121971e880d 100644 --- a/src/Symfony/Component/Intl/Intl.php +++ b/src/Symfony/Component/Intl/Intl.php @@ -113,14 +113,18 @@ public static function isExtensionLoaded() * Returns the bundle containing currency information. * * @return CurrencyBundleInterface The currency resource bundle + * + * @deprecated since Symfony 4.3, to be removed in 5.0. Use {@see Currencies} instead. */ public static function getCurrencyBundle() { + @trigger_error(sprintf('The method "%s()" is deprecated since Symfony 4.3, use "%s" instead.', __METHOD__, Currencies::class), E_USER_DEPRECATED); + if (null === self::$currencyBundle) { self::$currencyBundle = new CurrencyBundle( self::getDataDirectory().'/'.self::CURRENCY_DIR, self::getEntryReader(), - self::getLocaleBundle() + self::$localeBundle ?? self::$localeBundle = new LocaleBundle(self::getDataDirectory().'/'.self::LOCALE_DIR, self::getEntryReader()) ); } @@ -131,14 +135,18 @@ public static function getCurrencyBundle() * Returns the bundle containing language information. * * @return LanguageBundleInterface The language resource bundle + * + * @deprecated since Symfony 4.3, to be removed in 5.0. Use {@see Languages} or {@see Scripts} instead. */ public static function getLanguageBundle() { + @trigger_error(sprintf('The method "%s()" is deprecated since Symfony 4.3, use "%s" or "%s" instead.', __METHOD__, Languages::class, Scripts::class), E_USER_DEPRECATED); + if (null === self::$languageBundle) { self::$languageBundle = new LanguageBundle( self::getDataDirectory().'/'.self::LANGUAGE_DIR, self::getEntryReader(), - self::getLocaleBundle(), + self::$localeBundle ?? self::$localeBundle = new LocaleBundle(self::getDataDirectory().'/'.self::LOCALE_DIR, self::getEntryReader()), new ScriptDataProvider( self::getDataDirectory().'/'.self::SCRIPT_DIR, self::getEntryReader() @@ -153,9 +161,13 @@ public static function getLanguageBundle() * Returns the bundle containing locale information. * * @return LocaleBundleInterface The locale resource bundle + * + * @deprecated since Symfony 4.3, to be removed in 5.0. Use {@see Locales} instead. */ public static function getLocaleBundle() { + @trigger_error(sprintf('The method "%s()" is deprecated since Symfony 4.3, use "%s" instead.', __METHOD__, Locales::class), E_USER_DEPRECATED); + if (null === self::$localeBundle) { self::$localeBundle = new LocaleBundle( self::getDataDirectory().'/'.self::LOCALE_DIR, @@ -170,14 +182,18 @@ public static function getLocaleBundle() * Returns the bundle containing region information. * * @return RegionBundleInterface The region resource bundle + * + * @deprecated since Symfony 4.3, to be removed in 5.0. Use {@see Regions} instead. */ public static function getRegionBundle() { + @trigger_error(sprintf('The method "%s()" is deprecated since Symfony 4.3, use "%s" instead.', __METHOD__, Regions::class), E_USER_DEPRECATED); + if (null === self::$regionBundle) { self::$regionBundle = new RegionBundle( self::getDataDirectory().'/'.self::REGION_DIR, self::getEntryReader(), - self::getLocaleBundle() + self::$localeBundle ?? self::$localeBundle = new LocaleBundle(self::getDataDirectory().'/'.self::LOCALE_DIR, self::getEntryReader()) ); } diff --git a/src/Symfony/Component/Intl/Languages.php b/src/Symfony/Component/Intl/Languages.php new file mode 100644 index 0000000000000..64d85a6ade3ec --- /dev/null +++ b/src/Symfony/Component/Intl/Languages.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl; + +use Symfony\Component\Intl\Exception\MissingResourceException; + +/** + * Gives access to language-related ICU data. + * + * @author Bernhard Schussek + * @author Roland Franssen + */ +final class Languages extends ResourceBundle +{ + /** + * Returns all available languages. + * + * Languages are returned as lowercase ISO 639-1 two-letter language codes. + * For languages that don't have a two-letter code, the ISO 639-2 + * three-letter code is used instead. + * + * A full table of ISO 639 language codes can be found here: + * http://www-01.sil.org/iso639-3/codes.asp + * + * @return string[] an array of canonical ISO 639 language codes + */ + public static function getLanguageCodes(): array + { + return self::readEntry(['Languages'], 'meta'); + } + + public static function exists(string $language): bool + { + try { + self::readEntry(['Names', $language]); + + return true; + } catch (MissingResourceException $e) { + return false; + } + } + + public static function getName(string $language, string $displayLocale = null): string + { + return self::readEntry(['Names', $language], $displayLocale); + } + + /** + * @return string[] + */ + public static function getNames(string $displayLocale = null): array + { + return self::asort(self::readEntry(['Names'], $displayLocale), $displayLocale); + } + + /** + * Returns the ISO 639-2 three-letter code of a language. + * + * @throws MissingResourceException if the language has no corresponding three-letter code + */ + public static function getAlpha3Code(string $language): string + { + return self::readEntry(['Alpha2ToAlpha3', $language], 'meta'); + } + + protected static function getPath(): string + { + return Intl::getDataDirectory().'/'.Intl::LANGUAGE_DIR; + } +} diff --git a/src/Symfony/Component/Intl/Locales.php b/src/Symfony/Component/Intl/Locales.php new file mode 100644 index 0000000000000..980c8f8b6b679 --- /dev/null +++ b/src/Symfony/Component/Intl/Locales.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl; + +use Symfony\Component\Intl\Exception\MissingResourceException; + +/** + * Gives access to locale-related ICU data. + * + * @author Bernhard Schussek + * @author Roland Franssen + */ +final class Locales extends ResourceBundle +{ + /** + * @return string[] + */ + public static function getLocales(): array + { + return self::readEntry(['Locales'], 'meta'); + } + + /** + * @return string[] + */ + public static function getAliases(): array + { + return self::readEntry(['Aliases'], 'meta'); + } + + public static function exists(string $locale): bool + { + try { + self::readEntry(['Names', $locale]); + + return true; + } catch (MissingResourceException $e) { + return false; + } + } + + public static function getName(string $locale, string $displayLocale = null): string + { + return self::readEntry(['Names', $locale], $displayLocale); + } + + /** + * @return string[] + */ + public static function getNames($displayLocale = null) + { + return self::asort(self::readEntry(['Names'], $displayLocale), $displayLocale); + } + + protected static function getPath(): string + { + return Intl::getDataDirectory().'/'.Intl::LOCALE_DIR; + } +} diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php index c668d9a3c13ca..9f644ef8cd6ae 100644 --- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php +++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php @@ -11,12 +11,12 @@ namespace Symfony\Component\Intl\NumberFormatter; +use Symfony\Component\Intl\Currencies; use Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException; use Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException; use Symfony\Component\Intl\Exception\MethodNotImplementedException; use Symfony\Component\Intl\Exception\NotImplementedException; use Symfony\Component\Intl\Globals\IntlGlobals; -use Symfony\Component\Intl\Intl; use Symfony\Component\Intl\Locale\Locale; /** @@ -318,8 +318,8 @@ public function formatCurrency($value, $currency) return $this->format($value); } - $symbol = Intl::getCurrencyBundle()->getCurrencySymbol($currency, 'en'); - $fractionDigits = Intl::getCurrencyBundle()->getFractionDigits($currency); + $symbol = Currencies::getSymbol($currency, 'en'); + $fractionDigits = Currencies::getFractionDigits($currency); $value = $this->roundCurrency($value, $currency); @@ -682,8 +682,8 @@ protected function resetError() */ private function roundCurrency($value, $currency) { - $fractionDigits = Intl::getCurrencyBundle()->getFractionDigits($currency); - $roundingIncrement = Intl::getCurrencyBundle()->getRoundingIncrement($currency); + $fractionDigits = Currencies::getFractionDigits($currency); + $roundingIncrement = Currencies::getRoundingIncrement($currency); // Round with the formatter rounding mode $value = $this->round($value, $fractionDigits); diff --git a/src/Symfony/Component/Intl/Regions.php b/src/Symfony/Component/Intl/Regions.php new file mode 100644 index 0000000000000..b3606c0b30197 --- /dev/null +++ b/src/Symfony/Component/Intl/Regions.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl; + +use Symfony\Component\Intl\Exception\MissingResourceException; + +/** + * Gives access to region-related ICU data. + * + * @author Bernhard Schussek + * @author Roland Franssen + */ +final class Regions extends ResourceBundle +{ + /** + * @return string[] + */ + public static function getRegionCodes(): array + { + return self::readEntry(['Regions'], 'meta'); + } + + public static function exists(string $region): bool + { + try { + self::readEntry(['Names', $region]); + + return true; + } catch (MissingResourceException $e) { + return false; + } + } + + public static function getName(string $region, string $displayLocale = null): string + { + return self::readEntry(['Names', $region], $displayLocale); + } + + /** + * @return string[] + */ + public static function getNames($displayLocale = null) + { + return self::asort(self::readEntry(['Names'], $displayLocale), $displayLocale); + } + + protected static function getPath(): string + { + return Intl::getDataDirectory().'/'.Intl::REGION_DIR; + } +} diff --git a/src/Symfony/Component/Intl/ResourceBundle.php b/src/Symfony/Component/Intl/ResourceBundle.php new file mode 100644 index 0000000000000..46115838cdb7a --- /dev/null +++ b/src/Symfony/Component/Intl/ResourceBundle.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl; + +use Symfony\Component\Intl\Data\Bundle\Reader\BufferedBundleReader; +use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReader; +use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface; +use Symfony\Component\Intl\Data\Bundle\Reader\JsonBundleReader; + +/** + * @author Roland Franssen + * + * @internal + */ +abstract class ResourceBundle +{ + private static $entryReader; + + abstract protected static function getPath(): string; + + /** + * Reads an entry from a resource bundle. + * + * @see BundleEntryReaderInterface::readEntry() + * + * @param string[] $indices The indices to read from the bundle + * @param string $locale The locale to read + * @param bool $fallback Whether to merge the value with the value from + * the fallback locale (e.g. "en" for "en_GB"). + * Only applicable if the result is multivalued + * (i.e. array or \ArrayAccess) or cannot be found + * in the requested locale. + * + * @return mixed returns an array or {@link \ArrayAccess} instance for + * complex data and a scalar value for simple data + */ + final protected static function readEntry(array $indices, string $locale = null, bool $fallback = true) + { + if (null === self::$entryReader) { + self::$entryReader = new BundleEntryReader(new BufferedBundleReader( + new JsonBundleReader(), + Intl::BUFFER_SIZE + )); + + $localeAliases = self::$entryReader->readEntry(Intl::getDataDirectory().'/'.Intl::LOCALE_DIR, 'meta', ['Aliases']); + self::$entryReader->setLocaleAliases($localeAliases instanceof \Traversable ? iterator_to_array($localeAliases) : $localeAliases); + } + + return self::$entryReader->readEntry(static::getPath(), $locale ?? \Locale::getDefault(), $indices, $fallback); + } + + final protected static function asort(iterable $list, string $locale = null): array + { + if ($list instanceof \Traversable) { + $list = iterator_to_array($list); + } + + $collator = new \Collator($locale ?? \Locale::getDefault()); + $collator->asort($list); + + return $list; + } + + private function __construct() + { + } +} diff --git a/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundle.php b/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundle.php index 86e020570f7ac..b7ea33ea58574 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundle.php +++ b/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundle.php @@ -21,7 +21,7 @@ * * @author Bernhard Schussek * - * @internal + * @internal to be removed in 5.0. */ class CurrencyBundle extends CurrencyDataProvider implements CurrencyBundleInterface { diff --git a/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundleInterface.php b/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundleInterface.php index eb82f6849e6a4..421973b9fed31 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundleInterface.php +++ b/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundleInterface.php @@ -15,6 +15,8 @@ * Gives access to currency-related ICU data. * * @author Bernhard Schussek + * + * @deprecated since Symfony 4.3, to be removed in 5.0. */ interface CurrencyBundleInterface extends ResourceBundleInterface { diff --git a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php index b2fbde3fe5430..eabd94821db2c 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php +++ b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php @@ -22,7 +22,7 @@ * * @author Bernhard Schussek * - * @internal + * @internal to be removed in 5.0. */ class LanguageBundle extends LanguageDataProvider implements LanguageBundleInterface { diff --git a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundleInterface.php b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundleInterface.php index aa0c3e0f2c0b6..ab2c1805d145b 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundleInterface.php +++ b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundleInterface.php @@ -15,6 +15,8 @@ * Gives access to language-related ICU data. * * @author Bernhard Schussek + * + * @deprecated since Symfony 4.3, to be removed in 5.0. */ interface LanguageBundleInterface extends ResourceBundleInterface { diff --git a/src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php b/src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php index 078b1de2ddd8e..19acc41782cf2 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php +++ b/src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php @@ -19,7 +19,7 @@ * * @author Bernhard Schussek * - * @internal + * @internal to be removed in 5.0. */ class LocaleBundle extends LocaleDataProvider implements LocaleBundleInterface { diff --git a/src/Symfony/Component/Intl/ResourceBundle/LocaleBundleInterface.php b/src/Symfony/Component/Intl/ResourceBundle/LocaleBundleInterface.php index 6fa4e5c0abbf5..f7791adcbfec7 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/LocaleBundleInterface.php +++ b/src/Symfony/Component/Intl/ResourceBundle/LocaleBundleInterface.php @@ -15,6 +15,8 @@ * Gives access to locale-related ICU data. * * @author Bernhard Schussek + * + * @deprecated since Symfony 4.3, to be removed in 5.0. */ interface LocaleBundleInterface extends ResourceBundleInterface { diff --git a/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php b/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php index b5717a000f205..4cb34c2a09dda 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php +++ b/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php @@ -21,7 +21,7 @@ * * @author Bernhard Schussek * - * @internal + * @internal to be removed in 5.0. */ class RegionBundle extends RegionDataProvider implements RegionBundleInterface { diff --git a/src/Symfony/Component/Intl/ResourceBundle/RegionBundleInterface.php b/src/Symfony/Component/Intl/ResourceBundle/RegionBundleInterface.php index 12d0dd240824c..a417dbb3812da 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/RegionBundleInterface.php +++ b/src/Symfony/Component/Intl/ResourceBundle/RegionBundleInterface.php @@ -15,6 +15,8 @@ * Gives access to region-related ICU data. * * @author Bernhard Schussek + * + * @deprecated since Symfony 4.3, to be removed in 5.0. */ interface RegionBundleInterface extends ResourceBundleInterface { diff --git a/src/Symfony/Component/Intl/ResourceBundle/ResourceBundleInterface.php b/src/Symfony/Component/Intl/ResourceBundle/ResourceBundleInterface.php index 5c4c97483da94..37ef2648bddc9 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/ResourceBundleInterface.php +++ b/src/Symfony/Component/Intl/ResourceBundle/ResourceBundleInterface.php @@ -15,6 +15,8 @@ * Gives access to ICU data. * * @author Bernhard Schussek + * + * @deprecated since Symfony 4.3, to be removed in 5.0. */ interface ResourceBundleInterface { diff --git a/src/Symfony/Component/Intl/Scripts.php b/src/Symfony/Component/Intl/Scripts.php new file mode 100644 index 0000000000000..b01ff848efb97 --- /dev/null +++ b/src/Symfony/Component/Intl/Scripts.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl; + +use Symfony\Component\Intl\Exception\MissingResourceException; + +/** + * Gives access to script-related ICU data. + * + * @author Bernhard Schussek + * @author Roland Franssen + */ +final class Scripts extends ResourceBundle +{ + /** + * @return string[] + */ + public static function getScriptCodes(): array + { + return self::readEntry(['Scripts'], 'meta'); + } + + public static function exists(string $script): bool + { + try { + self::readEntry(['Names', $script]); + + return true; + } catch (MissingResourceException $e) { + return false; + } + } + + public static function getName(string $script, string $displayLocale = null): string + { + return self::readEntry(['Names', $script], $displayLocale); + } + + /** + * @return string[] + */ + public static function getNames($displayLocale = null) + { + return self::asort(self::readEntry(['Names'], $displayLocale), $displayLocale); + } + + protected static function getPath(): string + { + return Intl::getDataDirectory().'/'.Intl::SCRIPT_DIR; + } +} diff --git a/src/Symfony/Component/Intl/Tests/CurrenciesTest.php b/src/Symfony/Component/Intl/Tests/CurrenciesTest.php new file mode 100644 index 0000000000000..1f1a4e567b7a8 --- /dev/null +++ b/src/Symfony/Component/Intl/Tests/CurrenciesTest.php @@ -0,0 +1,789 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl\Tests; + +use Symfony\Component\Intl\Currencies; +use Symfony\Component\Intl\Locale; + +/** + * @group intl-data + */ +class CurrenciesTest extends ResourceBundleTestCase +{ + // The below arrays document the state of the ICU data bundled with this package. + + private static $currencies = [ + 'ADP', + 'AED', + 'AFA', + 'AFN', + 'ALK', + 'ALL', + 'AMD', + 'ANG', + 'AOA', + 'AOK', + 'AON', + 'AOR', + 'ARA', + 'ARL', + 'ARM', + 'ARP', + 'ARS', + 'ATS', + 'AUD', + 'AWG', + 'AZM', + 'AZN', + 'BAD', + 'BAM', + 'BAN', + 'BBD', + 'BDT', + 'BEC', + 'BEF', + 'BEL', + 'BGL', + 'BGM', + 'BGN', + 'BGO', + 'BHD', + 'BIF', + 'BMD', + 'BND', + 'BOB', + 'BOL', + 'BOP', + 'BOV', + 'BRB', + 'BRC', + 'BRE', + 'BRL', + 'BRN', + 'BRR', + 'BRZ', + 'BSD', + 'BTN', + 'BUK', + 'BWP', + 'BYB', + 'BYN', + 'BYR', + 'BZD', + 'CAD', + 'CDF', + 'CHE', + 'CHF', + 'CHW', + 'CLE', + 'CLF', + 'CLP', + 'CNH', + 'CNX', + 'CNY', + 'COP', + 'COU', + 'CRC', + 'CSD', + 'CSK', + 'CUC', + 'CUP', + 'CVE', + 'CYP', + 'CZK', + 'DDM', + 'DEM', + 'DJF', + 'DKK', + 'DOP', + 'DZD', + 'ECS', + 'ECV', + 'EEK', + 'EGP', + 'ERN', + 'ESA', + 'ESB', + 'ESP', + 'ETB', + 'EUR', + 'FIM', + 'FJD', + 'FKP', + 'FRF', + 'GBP', + 'GEK', + 'GEL', + 'GHC', + 'GHS', + 'GIP', + 'GMD', + 'GNF', + 'GNS', + 'GQE', + 'GRD', + 'GTQ', + 'GWE', + 'GWP', + 'GYD', + 'HKD', + 'HNL', + 'HRD', + 'HRK', + 'HTG', + 'HUF', + 'IDR', + 'IEP', + 'ILP', + 'ILR', + 'ILS', + 'INR', + 'IQD', + 'IRR', + 'ISJ', + 'ISK', + 'ITL', + 'JMD', + 'JOD', + 'JPY', + 'KES', + 'KGS', + 'KHR', + 'KMF', + 'KPW', + 'KRH', + 'KRO', + 'KRW', + 'KWD', + 'KYD', + 'KZT', + 'LAK', + 'LBP', + 'LKR', + 'LRD', + 'LSL', + 'LTL', + 'LTT', + 'LUC', + 'LUF', + 'LUL', + 'LVL', + 'LVR', + 'LYD', + 'MAD', + 'MAF', + 'MCF', + 'MDC', + 'MDL', + 'MGA', + 'MGF', + 'MKD', + 'MKN', + 'MLF', + 'MMK', + 'MNT', + 'MOP', + 'MRO', + 'MRU', + 'MTL', + 'MTP', + 'MUR', + 'MVP', + 'MVR', + 'MWK', + 'MXN', + 'MXP', + 'MXV', + 'MYR', + 'MZE', + 'MZM', + 'MZN', + 'NAD', + 'NGN', + 'NIC', + 'NIO', + 'NLG', + 'NOK', + 'NPR', + 'NZD', + 'OMR', + 'PAB', + 'PEI', + 'PEN', + 'PES', + 'PGK', + 'PHP', + 'PKR', + 'PLN', + 'PLZ', + 'PTE', + 'PYG', + 'QAR', + 'RHD', + 'ROL', + 'RON', + 'RSD', + 'RUB', + 'RUR', + 'RWF', + 'SAR', + 'SBD', + 'SCR', + 'SDD', + 'SDG', + 'SDP', + 'SEK', + 'SGD', + 'SHP', + 'SIT', + 'SKK', + 'SLL', + 'SOS', + 'SRD', + 'SRG', + 'SSP', + 'STD', + 'STN', + 'SUR', + 'SVC', + 'SYP', + 'SZL', + 'THB', + 'TJR', + 'TJS', + 'TMM', + 'TMT', + 'TND', + 'TOP', + 'TPE', + 'TRL', + 'TRY', + 'TTD', + 'TWD', + 'TZS', + 'UAH', + 'UAK', + 'UGS', + 'UGX', + 'USD', + 'USN', + 'USS', + 'UYI', + 'UYP', + 'UYU', + 'UYW', + 'UZS', + 'VEB', + 'VEF', + 'VES', + 'VND', + 'VNN', + 'VUV', + 'WST', + 'XAF', + 'XCD', + 'XEU', + 'XFO', + 'XFU', + 'XOF', + 'XPF', + 'XRE', + 'YDD', + 'YER', + 'YUD', + 'YUM', + 'YUN', + 'YUR', + 'ZAL', + 'ZAR', + 'ZMK', + 'ZMW', + 'ZRN', + 'ZRZ', + 'ZWD', + 'ZWL', + 'ZWR', + ]; + + private static $alpha3ToNumeric = [ + 'AFA' => 4, + 'ALK' => 8, + 'ALL' => 8, + 'DZD' => 12, + 'ADP' => 20, + 'AON' => 24, + 'AOK' => 24, + 'AZM' => 31, + 'ARA' => 32, + 'ARP' => 32, + 'ARS' => 32, + 'AUD' => 36, + 'ATS' => 40, + 'BSD' => 44, + 'BHD' => 48, + 'BDT' => 50, + 'AMD' => 51, + 'BBD' => 52, + 'BEF' => 56, + 'BMD' => 60, + 'BTN' => 64, + 'BOB' => 68, + 'BOP' => 68, + 'BAD' => 70, + 'BWP' => 72, + 'BRN' => 76, + 'BRE' => 76, + 'BRC' => 76, + 'BRB' => 76, + 'BZD' => 84, + 'SBD' => 90, + 'BND' => 96, + 'BGL' => 100, + 'MMK' => 104, + 'BUK' => 104, + 'BIF' => 108, + 'BYB' => 112, + 'KHR' => 116, + 'CAD' => 124, + 'CVE' => 132, + 'KYD' => 136, + 'LKR' => 144, + 'CLP' => 152, + 'CNY' => 156, + 'COP' => 170, + 'KMF' => 174, + 'ZRZ' => 180, + 'ZRN' => 180, + 'CRC' => 188, + 'HRK' => 191, + 'HRD' => 191, + 'CUP' => 192, + 'CYP' => 196, + 'CSK' => 200, + 'CZK' => 203, + 'DKK' => 208, + 'DOP' => 214, + 'ECS' => 218, + 'SVC' => 222, + 'GQE' => 226, + 'ETB' => 230, + 'ERN' => 232, + 'EEK' => 233, + 'FKP' => 238, + 'FJD' => 242, + 'FIM' => 246, + 'FRF' => 250, + 'DJF' => 262, + 'GEK' => 268, + 'GMD' => 270, + 'DEM' => 276, + 'DDM' => 278, + 'GHC' => 288, + 'GIP' => 292, + 'GRD' => 300, + 'GTQ' => 320, + 'GNS' => 324, + 'GNF' => 324, + 'GYD' => 328, + 'HTG' => 332, + 'HNL' => 340, + 'HKD' => 344, + 'HUF' => 348, + 'ISJ' => 352, + 'ISK' => 352, + 'INR' => 356, + 'IDR' => 360, + 'IRR' => 364, + 'IQD' => 368, + 'IEP' => 372, + 'ILP' => 376, + 'ILR' => 376, + 'ILS' => 376, + 'ITL' => 380, + 'JMD' => 388, + 'JPY' => 392, + 'KZT' => 398, + 'JOD' => 400, + 'KES' => 404, + 'KPW' => 408, + 'KRW' => 410, + 'KWD' => 414, + 'KGS' => 417, + 'LAK' => 418, + 'LBP' => 422, + 'LSL' => 426, + 'LVR' => 428, + 'LVL' => 428, + 'LRD' => 430, + 'LYD' => 434, + 'LTL' => 440, + 'LTT' => 440, + 'LUF' => 442, + 'MOP' => 446, + 'MGF' => 450, + 'MWK' => 454, + 'MYR' => 458, + 'MVR' => 462, + 'MLF' => 466, + 'MTL' => 470, + 'MTP' => 470, + 'MRO' => 478, + 'MUR' => 480, + 'MXP' => 484, + 'MXN' => 484, + 'MNT' => 496, + 'MDL' => 498, + 'MAD' => 504, + 'MZE' => 508, + 'MZM' => 508, + 'OMR' => 512, + 'NAD' => 516, + 'NPR' => 524, + 'NLG' => 528, + 'ANG' => 532, + 'AWG' => 533, + 'VUV' => 548, + 'NZD' => 554, + 'NIC' => 558, + 'NIO' => 558, + 'NGN' => 566, + 'NOK' => 578, + 'PKR' => 586, + 'PAB' => 590, + 'PGK' => 598, + 'PYG' => 600, + 'PEI' => 604, + 'PES' => 604, + 'PEN' => 604, + 'PHP' => 608, + 'PLZ' => 616, + 'PTE' => 620, + 'GWP' => 624, + 'GWE' => 624, + 'TPE' => 626, + 'QAR' => 634, + 'ROL' => 642, + 'RUB' => 643, + 'RWF' => 646, + 'SHP' => 654, + 'STD' => 678, + 'SAR' => 682, + 'SCR' => 690, + 'SLL' => 694, + 'SGD' => 702, + 'SKK' => 703, + 'VND' => 704, + 'SIT' => 705, + 'SOS' => 706, + 'ZAR' => 710, + 'ZWD' => 716, + 'RHD' => 716, + 'YDD' => 720, + 'ESP' => 724, + 'SSP' => 728, + 'SDD' => 736, + 'SDP' => 736, + 'SRG' => 740, + 'SZL' => 748, + 'SEK' => 752, + 'CHF' => 756, + 'SYP' => 760, + 'TJR' => 762, + 'THB' => 764, + 'TOP' => 776, + 'TTD' => 780, + 'AED' => 784, + 'TND' => 788, + 'TRL' => 792, + 'TMM' => 795, + 'UGX' => 800, + 'UGS' => 800, + 'UAK' => 804, + 'MKD' => 807, + 'RUR' => 810, + 'SUR' => 810, + 'EGP' => 818, + 'GBP' => 826, + 'TZS' => 834, + 'USD' => 840, + 'UYP' => 858, + 'UYU' => 858, + 'UZS' => 860, + 'VEB' => 862, + 'WST' => 882, + 'YER' => 886, + 'YUN' => 890, + 'YUD' => 890, + 'YUM' => 891, + 'CSD' => 891, + 'ZMK' => 894, + 'TWD' => 901, + 'UYW' => 927, + 'VES' => 928, + 'MRU' => 929, + 'STN' => 930, + 'CUC' => 931, + 'ZWL' => 932, + 'BYN' => 933, + 'TMT' => 934, + 'ZWR' => 935, + 'GHS' => 936, + 'VEF' => 937, + 'SDG' => 938, + 'UYI' => 940, + 'RSD' => 941, + 'MZN' => 943, + 'AZN' => 944, + 'RON' => 946, + 'CHE' => 947, + 'CHW' => 948, + 'TRY' => 949, + 'XAF' => 950, + 'XCD' => 951, + 'XOF' => 952, + 'XPF' => 953, + 'XEU' => 954, + 'ZMW' => 967, + 'SRD' => 968, + 'MGA' => 969, + 'COU' => 970, + 'AFN' => 971, + 'TJS' => 972, + 'AOA' => 973, + 'BYR' => 974, + 'BGN' => 975, + 'CDF' => 976, + 'BAM' => 977, + 'EUR' => 978, + 'MXV' => 979, + 'UAH' => 980, + 'GEL' => 981, + 'AOR' => 982, + 'ECV' => 983, + 'BOV' => 984, + 'PLN' => 985, + 'BRL' => 986, + 'BRR' => 987, + 'LUL' => 988, + 'LUC' => 989, + 'CLF' => 990, + 'ZAL' => 991, + 'BEL' => 992, + 'BEC' => 993, + 'ESB' => 995, + 'ESA' => 996, + 'USN' => 997, + 'USS' => 998, + ]; + + public function testGetCurrencies() + { + $this->assertSame(self::$currencies, Currencies::getCurrencyCodes()); + } + + /** + * @dataProvider provideLocales + */ + public function testGetNames($displayLocale) + { + $names = Currencies::getNames($displayLocale); + + $keys = array_keys($names); + + sort($keys); + + $this->assertSame(self::$currencies, $keys); + + // Names should be sorted + $sortedNames = $names; + $collator = new \Collator($displayLocale); + $collator->asort($names); + + $this->assertSame($sortedNames, $names); + } + + public function testGetNamesDefaultLocale() + { + Locale::setDefault('de_AT'); + + $this->assertSame(Currencies::getNames('de_AT'), Currencies::getNames()); + } + + /** + * @dataProvider provideLocaleAliases + */ + public function testGetNamesSupportsAliases($alias, $ofLocale) + { + // Can't use assertSame(), because some aliases contain scripts with + // different collation (=order of output) than their aliased locale + // e.g. sr_Latn_ME => sr_ME + $this->assertEquals(Currencies::getNames($ofLocale), Currencies::getNames($alias)); + } + + /** + * @dataProvider provideLocales + */ + public function testGetName($displayLocale) + { + $expected = Currencies::getNames($displayLocale); + $actual = []; + + foreach ($expected as $currency => $name) { + $actual[$currency] = Currencies::getName($currency, $displayLocale); + } + + $this->assertSame($expected, $actual); + } + + public function testGetNameDefaultLocale() + { + Locale::setDefault('de_AT'); + + $expected = Currencies::getNames('de_AT'); + $actual = []; + + foreach ($expected as $currency => $name) { + $actual[$currency] = Currencies::getName($currency); + } + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider provideLocales + */ + public function testGetSymbol($displayLocale) + { + $currencies = Currencies::getCurrencyCodes(); + + foreach ($currencies as $currency) { + $this->assertGreaterThan(0, mb_strlen(Currencies::getSymbol($currency, $displayLocale))); + } + } + + public function provideCurrencies() + { + return array_map( + function ($currency) { return [$currency]; }, + self::$currencies + ); + } + + /** + * @dataProvider provideCurrencies + */ + public function testGetFractionDigits($currency) + { + $this->assertInternalType('numeric', Currencies::getFractionDigits($currency)); + } + + /** + * @dataProvider provideCurrencies + */ + public function testGetRoundingIncrement($currency) + { + $this->assertInternalType('numeric', Currencies::getRoundingIncrement($currency)); + } + + public function provideCurrenciesWithNumericEquivalent() + { + return array_map( + function ($value) { return [$value]; }, + array_keys(self::$alpha3ToNumeric) + ); + } + + /** + * @dataProvider provideCurrenciesWithNumericEquivalent + */ + public function testGetNumericCode($currency) + { + $this->assertSame(self::$alpha3ToNumeric[$currency], Currencies::getNumericCode($currency)); + } + + public function provideCurrenciesWithoutNumericEquivalent() + { + return array_map( + function ($value) { return [$value]; }, + array_diff(self::$currencies, array_keys(self::$alpha3ToNumeric)) + ); + } + + /** + * @dataProvider provideCurrenciesWithoutNumericEquivalent + * @expectedException \Symfony\Component\Intl\Exception\MissingResourceException + */ + public function testGetNumericCodeFailsIfNoNumericEquivalent($currency) + { + Currencies::getNumericCode($currency); + } + + public function provideValidNumericCodes() + { + $numericToAlpha3 = $this->getNumericToAlpha3Mapping(); + + return array_map( + function ($numeric, $alpha3) { return [$numeric, $alpha3]; }, + array_keys($numericToAlpha3), + $numericToAlpha3 + ); + } + + /** + * @dataProvider provideValidNumericCodes + */ + public function testForNumericCode($numeric, $expected) + { + $actual = Currencies::forNumericCode($numeric); + + // Make sure that a different array order doesn't break the test + sort($actual); + sort($expected); + + $this->assertSame($expected, $actual); + } + + public function provideInvalidNumericCodes() + { + $validNumericCodes = array_keys($this->getNumericToAlpha3Mapping()); + $invalidNumericCodes = array_diff(range(0, 1000), $validNumericCodes); + + return array_map( + function ($value) { return [$value]; }, + $invalidNumericCodes + ); + } + + /** + * @dataProvider provideInvalidNumericCodes + * @expectedException \Symfony\Component\Intl\Exception\MissingResourceException + */ + public function testForNumericCodeFailsIfInvalidNumericCode($currency) + { + Currencies::forNumericCode($currency); + } + + private function getNumericToAlpha3Mapping() + { + $numericToAlpha3 = []; + + foreach (self::$alpha3ToNumeric as $alpha3 => $numeric) { + if (!isset($numericToAlpha3[$numeric])) { + $numericToAlpha3[$numeric] = []; + } + + $numericToAlpha3[$numeric][] = $alpha3; + } + + return $numericToAlpha3; + } +} diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractCurrencyDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractCurrencyDataProviderTest.php index 428f6f89b0045..65140b9d2bd20 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractCurrencyDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractCurrencyDataProviderTest.php @@ -17,6 +17,8 @@ /** * @author Bernhard Schussek + * + * @group legacy */ abstract class AbstractCurrencyDataProviderTest extends AbstractDataProviderTest { diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractDataProviderTest.php index d0ef4d273b45a..b61f97c7a403c 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractDataProviderTest.php @@ -18,6 +18,8 @@ /** * @author Bernhard Schussek + * + * @group legacy */ abstract class AbstractDataProviderTest extends TestCase { diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLanguageDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLanguageDataProviderTest.php index 310fe791608f9..580b7ed951165 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLanguageDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLanguageDataProviderTest.php @@ -17,6 +17,8 @@ /** * @author Bernhard Schussek + * + * @group legacy */ abstract class AbstractLanguageDataProviderTest extends AbstractDataProviderTest { diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLocaleDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLocaleDataProviderTest.php index aeca40cdbd6cd..0fe89266002a9 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLocaleDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLocaleDataProviderTest.php @@ -17,6 +17,8 @@ /** * @author Bernhard Schussek + * + * @group legacy */ abstract class AbstractLocaleDataProviderTest extends AbstractDataProviderTest { diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractRegionDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractRegionDataProviderTest.php index 1f5febb2b86bf..0e0325cdb784c 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractRegionDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractRegionDataProviderTest.php @@ -17,6 +17,8 @@ /** * @author Bernhard Schussek + * + * @group legacy */ abstract class AbstractRegionDataProviderTest extends AbstractDataProviderTest { diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractScriptDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractScriptDataProviderTest.php index db4b81ebdb13f..669bbfa3459bb 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractScriptDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractScriptDataProviderTest.php @@ -18,6 +18,7 @@ /** * @author Bernhard Schussek * @group intl-data + * @group legacy */ abstract class AbstractScriptDataProviderTest extends AbstractDataProviderTest { diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonCurrencyDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonCurrencyDataProviderTest.php index 1baca128d687f..ff12edb44126b 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonCurrencyDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonCurrencyDataProviderTest.php @@ -19,6 +19,7 @@ /** * @author Bernhard Schussek * @group intl-data + * @group legacy */ class JsonCurrencyDataProviderTest extends AbstractCurrencyDataProviderTest { diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonLanguageDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonLanguageDataProviderTest.php index ba4c0ee08c143..74049ab53e13f 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonLanguageDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonLanguageDataProviderTest.php @@ -19,6 +19,7 @@ /** * @author Bernhard Schussek * @group intl-data + * @group legacy */ class JsonLanguageDataProviderTest extends AbstractLanguageDataProviderTest { diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonLocaleDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonLocaleDataProviderTest.php index 2e5e803b1d443..ba00439bdcea0 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonLocaleDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonLocaleDataProviderTest.php @@ -19,6 +19,7 @@ /** * @author Bernhard Schussek * @group intl-data + * @group legacy */ class JsonLocaleDataProviderTest extends AbstractLocaleDataProviderTest { diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonRegionDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonRegionDataProviderTest.php index c3dba262475ca..9bb3bba48917d 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonRegionDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonRegionDataProviderTest.php @@ -19,6 +19,7 @@ /** * @author Bernhard Schussek * @group intl-data + * @group legacy */ class JsonRegionDataProviderTest extends AbstractRegionDataProviderTest { diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonScriptDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonScriptDataProviderTest.php index ec1eede660cd8..9648cbaca306f 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonScriptDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/Json/JsonScriptDataProviderTest.php @@ -19,6 +19,7 @@ /** * @author Bernhard Schussek * @group intl-data + * @group legacy */ class JsonScriptDataProviderTest extends AbstractScriptDataProviderTest { diff --git a/src/Symfony/Component/Intl/Tests/IntlTest.php b/src/Symfony/Component/Intl/Tests/IntlTest.php index de722baf948f3..fd8f294a3841e 100644 --- a/src/Symfony/Component/Intl/Tests/IntlTest.php +++ b/src/Symfony/Component/Intl/Tests/IntlTest.php @@ -24,21 +24,33 @@ public function testIsExtensionLoadedChecksIfIntlExtensionIsLoaded() $this->assertTrue(Intl::isExtensionLoaded()); } + /** + * @group legacy + */ public function testGetCurrencyBundleCreatesTheCurrencyBundle() { $this->assertInstanceOf('Symfony\Component\Intl\ResourceBundle\CurrencyBundleInterface', Intl::getCurrencyBundle()); } + /** + * @group legacy + */ public function testGetLanguageBundleCreatesTheLanguageBundle() { $this->assertInstanceOf('Symfony\Component\Intl\ResourceBundle\LanguageBundleInterface', Intl::getLanguageBundle()); } + /** + * @group legacy + */ public function testGetLocaleBundleCreatesTheLocaleBundle() { $this->assertInstanceOf('Symfony\Component\Intl\ResourceBundle\LocaleBundleInterface', Intl::getLocaleBundle()); } + /** + * @group legacy + */ public function testGetRegionBundleCreatesTheRegionBundle() { $this->assertInstanceOf('Symfony\Component\Intl\ResourceBundle\RegionBundleInterface', Intl::getRegionBundle()); @@ -65,6 +77,7 @@ public function testGetDataDirectoryReturnsThePathToIcuData() } /** + * @group legacy * @requires extension intl */ public function testLocaleAliasesAreLoaded() diff --git a/src/Symfony/Component/Intl/Tests/LanguagesTest.php b/src/Symfony/Component/Intl/Tests/LanguagesTest.php new file mode 100644 index 0000000000000..6fa059b29445a --- /dev/null +++ b/src/Symfony/Component/Intl/Tests/LanguagesTest.php @@ -0,0 +1,918 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl\Tests; + +use Symfony\Component\Intl\Languages; +use Symfony\Component\Intl\Locale; + +/** + * @group intl-data + */ +class LanguagesTest extends ResourceBundleTestCase +{ + // The below arrays document the state of the ICU data bundled with this package. + + private static $languages = [ + 'aa', + 'ab', + 'ace', + 'ach', + 'ada', + 'ady', + 'ae', + 'aeb', + 'af', + 'afh', + 'agq', + 'ain', + 'ak', + 'akk', + 'akz', + 'ale', + 'aln', + 'alt', + 'am', + 'an', + 'ang', + 'anp', + 'ar', + 'ar_001', + 'arc', + 'arn', + 'aro', + 'arp', + 'arq', + 'ars', + 'arw', + 'ary', + 'arz', + 'as', + 'asa', + 'ase', + 'ast', + 'av', + 'avk', + 'awa', + 'ay', + 'az', + 'az_Arab', + 'ba', + 'bal', + 'ban', + 'bar', + 'bas', + 'bax', + 'bbc', + 'bbj', + 'be', + 'bej', + 'bem', + 'bew', + 'bez', + 'bfd', + 'bfq', + 'bg', + 'bgn', + 'bho', + 'bi', + 'bik', + 'bin', + 'bjn', + 'bkm', + 'bla', + 'bm', + 'bn', + 'bo', + 'bpy', + 'bqi', + 'br', + 'bra', + 'brh', + 'brx', + 'bs', + 'bss', + 'bua', + 'bug', + 'bum', + 'byn', + 'byv', + 'ca', + 'cad', + 'car', + 'cay', + 'cch', + 'ccp', + 'ce', + 'ceb', + 'cgg', + 'ch', + 'chb', + 'chg', + 'chk', + 'chm', + 'chn', + 'cho', + 'chp', + 'chr', + 'chy', + 'ckb', + 'co', + 'cop', + 'cps', + 'cr', + 'crh', + 'crs', + 'cs', + 'csb', + 'cu', + 'cv', + 'cy', + 'da', + 'dak', + 'dar', + 'dav', + 'de', + 'de_AT', + 'de_CH', + 'del', + 'den', + 'dgr', + 'din', + 'dje', + 'doi', + 'dsb', + 'dtp', + 'dua', + 'dum', + 'dv', + 'dyo', + 'dyu', + 'dz', + 'dzg', + 'ebu', + 'ee', + 'efi', + 'egl', + 'egy', + 'eka', + 'el', + 'elx', + 'en', + 'en_AU', + 'en_CA', + 'en_GB', + 'en_US', + 'enm', + 'eo', + 'es', + 'es_419', + 'es_ES', + 'es_MX', + 'esu', + 'et', + 'eu', + 'ewo', + 'ext', + 'fa', + 'fa_AF', + 'fan', + 'fat', + 'ff', + 'fi', + 'fil', + 'fit', + 'fj', + 'fo', + 'fon', + 'fr', + 'fr_CA', + 'fr_CH', + 'frc', + 'frm', + 'fro', + 'frp', + 'frr', + 'frs', + 'fur', + 'fy', + 'ga', + 'gaa', + 'gag', + 'gan', + 'gay', + 'gba', + 'gbz', + 'gd', + 'gez', + 'gil', + 'gl', + 'glk', + 'gmh', + 'gn', + 'goh', + 'gom', + 'gon', + 'gor', + 'got', + 'grb', + 'grc', + 'gsw', + 'gu', + 'guc', + 'gur', + 'guz', + 'gv', + 'gwi', + 'ha', + 'hai', + 'hak', + 'haw', + 'he', + 'hi', + 'hif', + 'hil', + 'hit', + 'hmn', + 'ho', + 'hr', + 'hsb', + 'hsn', + 'ht', + 'hu', + 'hup', + 'hy', + 'hz', + 'ia', + 'iba', + 'ibb', + 'id', + 'ie', + 'ig', + 'ii', + 'ik', + 'ilo', + 'inh', + 'io', + 'is', + 'it', + 'iu', + 'izh', + 'ja', + 'jam', + 'jbo', + 'jgo', + 'jmc', + 'jpr', + 'jrb', + 'jut', + 'jv', + 'ka', + 'kaa', + 'kab', + 'kac', + 'kaj', + 'kam', + 'kaw', + 'kbd', + 'kbl', + 'kcg', + 'kde', + 'kea', + 'ken', + 'kfo', + 'kg', + 'kgp', + 'kha', + 'kho', + 'khq', + 'khw', + 'ki', + 'kiu', + 'kj', + 'kk', + 'kkj', + 'kl', + 'kln', + 'km', + 'kmb', + 'kn', + 'ko', + 'koi', + 'kok', + 'kos', + 'kpe', + 'kr', + 'krc', + 'kri', + 'krj', + 'krl', + 'kru', + 'ks', + 'ksb', + 'ksf', + 'ksh', + 'ku', + 'kum', + 'kut', + 'kv', + 'kw', + 'ky', + 'la', + 'lad', + 'lag', + 'lah', + 'lam', + 'lb', + 'lez', + 'lfn', + 'lg', + 'li', + 'lij', + 'liv', + 'lkt', + 'lmo', + 'ln', + 'lo', + 'lol', + 'lou', + 'loz', + 'lrc', + 'lt', + 'ltg', + 'lu', + 'lua', + 'lui', + 'lun', + 'luo', + 'lus', + 'luy', + 'lv', + 'lzh', + 'lzz', + 'mad', + 'maf', + 'mag', + 'mai', + 'mak', + 'man', + 'mas', + 'mde', + 'mdf', + 'mdr', + 'men', + 'mer', + 'mfe', + 'mg', + 'mga', + 'mgh', + 'mgo', + 'mh', + 'mi', + 'mic', + 'min', + 'mk', + 'ml', + 'mn', + 'mnc', + 'mni', + 'moh', + 'mos', + 'mr', + 'mrj', + 'ms', + 'mt', + 'mua', + 'mus', + 'mwl', + 'mwr', + 'mwv', + 'my', + 'mye', + 'myv', + 'mzn', + 'na', + 'nan', + 'nap', + 'naq', + 'nb', + 'nd', + 'nds', + 'nds_NL', + 'ne', + 'new', + 'ng', + 'nia', + 'niu', + 'njo', + 'nl', + 'nl_BE', + 'nmg', + 'nn', + 'nnh', + 'no', + 'nog', + 'non', + 'nov', + 'nqo', + 'nr', + 'nso', + 'nus', + 'nv', + 'nwc', + 'ny', + 'nym', + 'nyn', + 'nyo', + 'nzi', + 'oc', + 'oj', + 'om', + 'or', + 'os', + 'osa', + 'ota', + 'pa', + 'pag', + 'pal', + 'pam', + 'pap', + 'pau', + 'pcd', + 'pcm', + 'pdc', + 'pdt', + 'peo', + 'pfl', + 'phn', + 'pi', + 'pl', + 'pms', + 'pnt', + 'pon', + 'prg', + 'pro', + 'ps', + 'pt', + 'pt_BR', + 'pt_PT', + 'qu', + 'quc', + 'qug', + 'raj', + 'rap', + 'rar', + 'rgn', + 'rif', + 'rm', + 'rn', + 'ro', + 'ro_MD', + 'rof', + 'rom', + 'root', + 'rtm', + 'ru', + 'rue', + 'rug', + 'rup', + 'rw', + 'rwk', + 'sa', + 'sad', + 'sah', + 'sam', + 'saq', + 'sas', + 'sat', + 'saz', + 'sba', + 'sbp', + 'sc', + 'scn', + 'sco', + 'sd', + 'sdc', + 'sdh', + 'se', + 'see', + 'seh', + 'sei', + 'sel', + 'ses', + 'sg', + 'sga', + 'sgs', + 'sh', + 'shi', + 'shn', + 'shu', + 'si', + 'sid', + 'sk', + 'sl', + 'sli', + 'sly', + 'sm', + 'sma', + 'smj', + 'smn', + 'sms', + 'sn', + 'snk', + 'so', + 'sog', + 'sq', + 'sr', + 'sr_ME', + 'srn', + 'srr', + 'ss', + 'ssy', + 'st', + 'stq', + 'su', + 'suk', + 'sus', + 'sux', + 'sv', + 'sw', + 'sw_CD', + 'swb', + 'syc', + 'syr', + 'szl', + 'ta', + 'tcy', + 'te', + 'tem', + 'teo', + 'ter', + 'tet', + 'tg', + 'th', + 'ti', + 'tig', + 'tiv', + 'tk', + 'tkl', + 'tkr', + 'tl', + 'tlh', + 'tli', + 'tly', + 'tmh', + 'tn', + 'to', + 'tog', + 'tpi', + 'tr', + 'tru', + 'trv', + 'ts', + 'tsd', + 'tsi', + 'tt', + 'ttt', + 'tum', + 'tvl', + 'tw', + 'twq', + 'ty', + 'tyv', + 'tzm', + 'udm', + 'ug', + 'uga', + 'uk', + 'umb', + 'ur', + 'uz', + 'vai', + 've', + 'vec', + 'vep', + 'vi', + 'vls', + 'vmf', + 'vo', + 'vot', + 'vro', + 'vun', + 'wa', + 'wae', + 'wal', + 'war', + 'was', + 'wbp', + 'wo', + 'wuu', + 'xal', + 'xh', + 'xmf', + 'xog', + 'yao', + 'yap', + 'yav', + 'ybb', + 'yi', + 'yo', + 'yrl', + 'yue', + 'za', + 'zap', + 'zbl', + 'zea', + 'zen', + 'zgh', + 'zh', + 'zh_Hans', + 'zh_Hant', + 'zu', + 'zun', + 'zza', + ]; + + private static $alpha2ToAlpha3 = [ + 'aa' => 'aar', + 'ab' => 'abk', + 'af' => 'afr', + 'ak' => 'aka', + 'sq' => 'sqi', + 'am' => 'amh', + 'ar' => 'ara', + 'an' => 'arg', + 'hy' => 'hye', + 'as' => 'asm', + 'av' => 'ava', + 'ae' => 'ave', + 'ay' => 'aym', + 'az' => 'aze', + 'ba' => 'bak', + 'bm' => 'bam', + 'eu' => 'eus', + 'be' => 'bel', + 'bn' => 'ben', + 'bi' => 'bis', + 'bo' => 'bod', + 'bs' => 'bos', + 'br' => 'bre', + 'bg' => 'bul', + 'my' => 'mya', + 'ca' => 'cat', + 'cs' => 'ces', + 'ch' => 'cha', + 'ce' => 'che', + 'zh' => 'zho', + 'cu' => 'chu', + 'cv' => 'chv', + 'kw' => 'cor', + 'co' => 'cos', + 'cr' => 'cre', + 'cy' => 'cym', + 'da' => 'dan', + 'de' => 'deu', + 'dv' => 'div', + 'nl' => 'nld', + 'dz' => 'dzo', + 'et' => 'est', + 'el' => 'ell', + 'en' => 'eng', + 'eo' => 'epo', + 'ik' => 'ipk', + 'ee' => 'ewe', + 'fo' => 'fao', + 'fa' => 'fas', + 'fj' => 'fij', + 'fi' => 'fin', + 'fr' => 'fra', + 'fy' => 'fry', + 'ff' => 'ful', + 'om' => 'orm', + 'ka' => 'kat', + 'gd' => 'gla', + 'ga' => 'gle', + 'gl' => 'glg', + 'gv' => 'glv', + 'gn' => 'grn', + 'gu' => 'guj', + 'ht' => 'hat', + 'ha' => 'hau', + 'he' => 'heb', + 'hz' => 'her', + 'hi' => 'hin', + 'ho' => 'hmo', + 'hr' => 'hrv', + 'hu' => 'hun', + 'ig' => 'ibo', + 'is' => 'isl', + 'io' => 'ido', + 'ii' => 'iii', + 'iu' => 'iku', + 'ie' => 'ile', + 'ia' => 'ina', + 'id' => 'ind', + 'it' => 'ita', + 'jv' => 'jav', + 'ja' => 'jpn', + 'kl' => 'kal', + 'kn' => 'kan', + 'ks' => 'kas', + 'kr' => 'kau', + 'kk' => 'kaz', + 'mn' => 'mon', + 'km' => 'khm', + 'ki' => 'kik', + 'rw' => 'kin', + 'ky' => 'kir', + 'ku' => 'kur', + 'kg' => 'kon', + 'kv' => 'kom', + 'ko' => 'kor', + 'kj' => 'kua', + 'lo' => 'lao', + 'la' => 'lat', + 'lv' => 'lav', + 'li' => 'lim', + 'ln' => 'lin', + 'lt' => 'lit', + 'lb' => 'ltz', + 'lu' => 'lub', + 'lg' => 'lug', + 'mk' => 'mkd', + 'mh' => 'mah', + 'ml' => 'mal', + 'mi' => 'mri', + 'mr' => 'mar', + 'ms' => 'msa', + 'mg' => 'mlg', + 'mt' => 'mlt', + 'na' => 'nau', + 'nv' => 'nav', + 'nr' => 'nbl', + 'nd' => 'nde', + 'ng' => 'ndo', + 'ne' => 'nep', + 'nn' => 'nno', + 'nb' => 'nob', + 'ny' => 'nya', + 'oc' => 'oci', + 'oj' => 'oji', + 'or' => 'ori', + 'os' => 'oss', + 'pa' => 'pan', + 'ps' => 'pus', + 'pi' => 'pli', + 'pl' => 'pol', + 'pt' => 'por', + 'qu' => 'que', + 'rm' => 'roh', + 'ro' => 'ron', + 'rn' => 'run', + 'ru' => 'rus', + 'sg' => 'sag', + 'sa' => 'san', + 'sr' => 'srp', + 'si' => 'sin', + 'sk' => 'slk', + 'sl' => 'slv', + 'se' => 'sme', + 'sm' => 'smo', + 'sn' => 'sna', + 'sd' => 'snd', + 'so' => 'som', + 'st' => 'sot', + 'es' => 'spa', + 'sc' => 'srd', + 'ss' => 'ssw', + 'su' => 'sun', + 'sw' => 'swa', + 'sv' => 'swe', + 'ty' => 'tah', + 'ta' => 'tam', + 'tt' => 'tat', + 'te' => 'tel', + 'tg' => 'tgk', + 'th' => 'tha', + 'ti' => 'tir', + 'to' => 'ton', + 'tn' => 'tsn', + 'ts' => 'tso', + 'tk' => 'tuk', + 'tr' => 'tur', + 'ug' => 'uig', + 'uk' => 'ukr', + 'ur' => 'urd', + 'uz' => 'uzb', + 've' => 'ven', + 'vi' => 'vie', + 'vo' => 'vol', + 'wa' => 'wln', + 'wo' => 'wol', + 'xh' => 'xho', + 'yi' => 'yid', + 'yo' => 'yor', + 'za' => 'zha', + 'zu' => 'zul', + ]; + + public function testGetLanguages() + { + $this->assertEquals(self::$languages, Languages::getLanguageCodes()); + } + + /** + * @dataProvider provideLocales + */ + public function testGetNames($displayLocale) + { + $languages = array_keys(Languages::getNames($displayLocale)); + + sort($languages); + + $this->assertNotEmpty($languages); + $this->assertEmpty(array_diff($languages, self::$languages)); + } + + public function testGetNamesDefaultLocale() + { + Locale::setDefault('de_AT'); + + $this->assertSame(Languages::getNames('de_AT'), Languages::getNames()); + } + + /** + * @dataProvider provideLocaleAliases + */ + public function testGetNamesSupportsAliases($alias, $ofLocale) + { + // Can't use assertSame(), because some aliases contain scripts with + // different collation (=order of output) than their aliased locale + // e.g. sr_Latn_ME => sr_ME + $this->assertEquals(Languages::getNames($ofLocale), Languages::getNames($alias)); + } + + /** + * @dataProvider provideLocales + */ + public function testGetName($displayLocale) + { + $names = Languages::getNames($displayLocale); + + foreach ($names as $language => $name) { + $this->assertSame($name, Languages::getName($language, $displayLocale)); + } + } + + public function testGetNameDefaultLocale() + { + Locale::setDefault('de_AT'); + + $names = Languages::getNames('de_AT'); + + foreach ($names as $language => $name) { + $this->assertSame($name, Languages::getName($language)); + } + } + + public function provideLanguagesWithAlpha3Equivalent() + { + return array_map( + function ($value) { return [$value]; }, + array_keys(self::$alpha2ToAlpha3) + ); + } + + /** + * @dataProvider provideLanguagesWithAlpha3Equivalent + */ + public function testGetAlpha3Code($language) + { + $this->assertSame(self::$alpha2ToAlpha3[$language], Languages::getAlpha3Code($language)); + } + + public function provideLanguagesWithoutAlpha3Equivalent() + { + return array_map( + function ($value) { return [$value]; }, + array_diff(self::$languages, array_keys(self::$alpha2ToAlpha3)) + ); + } + + /** + * @dataProvider provideLanguagesWithoutAlpha3Equivalent + * @expectedException \Symfony\Component\Intl\Exception\MissingResourceException + */ + public function testGetAlpha3CodeFailsIfNoAlpha3Equivalent($language) + { + Languages::getAlpha3Code($language); + } +} diff --git a/src/Symfony/Component/Intl/Tests/LocalesTest.php b/src/Symfony/Component/Intl/Tests/LocalesTest.php new file mode 100644 index 0000000000000..e7ffbd2ca9a42 --- /dev/null +++ b/src/Symfony/Component/Intl/Tests/LocalesTest.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl\Tests; + +use Symfony\Component\Intl\Locale; +use Symfony\Component\Intl\Locales; + +/** + * @group intl-data + */ +class LocalesTest extends ResourceBundleTestCase +{ + public function testGetLocales() + { + $this->assertSame($this->getLocales(), Locales::getLocales()); + } + + public function testGetLocaleAliases() + { + $this->assertSame($this->getLocaleAliases(), Locales::getAliases()); + } + + /** + * @dataProvider provideLocales + */ + public function testGetNames($displayLocale) + { + $locales = array_keys(Locales::getNames($displayLocale)); + + sort($locales); + + // We can't assert on exact list of locale, as there's too many variations. + // The best we can do is to make sure getNames() returns a subset of what getLocales() returns. + $this->assertNotEmpty($locales); + $this->assertEmpty(array_diff($locales, $this->getLocales())); + } + + public function testGetNamesDefaultLocale() + { + Locale::setDefault('de_AT'); + + $this->assertSame(Locales::getNames('de_AT'), Locales::getNames()); + } + + /** + * @dataProvider provideLocaleAliases + */ + public function testGetNamesSupportsAliases($alias, $ofLocale) + { + // Can't use assertSame(), because some aliases contain scripts with + // different collation (=order of output) than their aliased locale + // e.g. sr_Latn_ME => sr_ME + $this->assertEquals(Locales::getNames($ofLocale), Locales::getNames($alias)); + } + + /** + * @dataProvider provideLocales + */ + public function testGetName($displayLocale) + { + $names = Locales::getNames($displayLocale); + + foreach ($names as $locale => $name) { + $this->assertSame($name, Locales::getName($locale, $displayLocale)); + } + } + + public function testGetNameDefaultLocale() + { + Locale::setDefault('de_AT'); + + $names = Locales::getNames('de_AT'); + + foreach ($names as $locale => $name) { + $this->assertSame($name, Locales::getName($locale)); + } + } +} diff --git a/src/Symfony/Component/Intl/Tests/RegionsTest.php b/src/Symfony/Component/Intl/Tests/RegionsTest.php new file mode 100644 index 0000000000000..80d4ca98bf638 --- /dev/null +++ b/src/Symfony/Component/Intl/Tests/RegionsTest.php @@ -0,0 +1,346 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl\Tests; + +use Symfony\Component\Intl\Locale; +use Symfony\Component\Intl\Regions; + +/** + * @group intl-data + */ +class RegionsTest extends ResourceBundleTestCase +{ + // The below arrays document the state of the ICU data bundled with this package. + + private static $territories = [ + 'AC', + 'AD', + 'AE', + 'AF', + 'AG', + 'AI', + 'AL', + 'AM', + 'AO', + 'AQ', + 'AR', + 'AS', + 'AT', + 'AU', + 'AW', + 'AX', + 'AZ', + 'BA', + 'BB', + 'BD', + 'BE', + 'BF', + 'BG', + 'BH', + 'BI', + 'BJ', + 'BL', + 'BM', + 'BN', + 'BO', + 'BQ', + 'BR', + 'BS', + 'BT', + 'BW', + 'BY', + 'BZ', + 'CA', + 'CC', + 'CD', + 'CF', + 'CG', + 'CH', + 'CI', + 'CK', + 'CL', + 'CM', + 'CN', + 'CO', + 'CR', + 'CU', + 'CV', + 'CW', + 'CX', + 'CY', + 'CZ', + 'DE', + 'DG', + 'DJ', + 'DK', + 'DM', + 'DO', + 'DZ', + 'EA', + 'EC', + 'EE', + 'EG', + 'EH', + 'ER', + 'ES', + 'ET', + 'FI', + 'FJ', + 'FK', + 'FM', + 'FO', + 'FR', + 'GA', + 'GB', + 'GD', + 'GE', + 'GF', + 'GG', + 'GH', + 'GI', + 'GL', + 'GM', + 'GN', + 'GP', + 'GQ', + 'GR', + 'GS', + 'GT', + 'GU', + 'GW', + 'GY', + 'HK', + 'HN', + 'HR', + 'HT', + 'HU', + 'IC', + 'ID', + 'IE', + 'IL', + 'IM', + 'IN', + 'IO', + 'IQ', + 'IR', + 'IS', + 'IT', + 'JE', + 'JM', + 'JO', + 'JP', + 'KE', + 'KG', + 'KH', + 'KI', + 'KM', + 'KN', + 'KP', + 'KR', + 'KW', + 'KY', + 'KZ', + 'LA', + 'LB', + 'LC', + 'LI', + 'LK', + 'LR', + 'LS', + 'LT', + 'LU', + 'LV', + 'LY', + 'MA', + 'MC', + 'MD', + 'ME', + 'MF', + 'MG', + 'MH', + 'MK', + 'ML', + 'MM', + 'MN', + 'MO', + 'MP', + 'MQ', + 'MR', + 'MS', + 'MT', + 'MU', + 'MV', + 'MW', + 'MX', + 'MY', + 'MZ', + 'NA', + 'NC', + 'NE', + 'NF', + 'NG', + 'NI', + 'NL', + 'NO', + 'NP', + 'NR', + 'NU', + 'NZ', + 'OM', + 'PA', + 'PE', + 'PF', + 'PG', + 'PH', + 'PK', + 'PL', + 'PM', + 'PN', + 'PR', + 'PS', + 'PT', + 'PW', + 'PY', + 'QA', + 'RE', + 'RO', + 'RS', + 'RU', + 'RW', + 'SA', + 'SB', + 'SC', + 'SD', + 'SE', + 'SG', + 'SH', + 'SI', + 'SJ', + 'SK', + 'SL', + 'SM', + 'SN', + 'SO', + 'SR', + 'SS', + 'ST', + 'SV', + 'SX', + 'SY', + 'SZ', + 'TA', + 'TC', + 'TD', + 'TF', + 'TG', + 'TH', + 'TJ', + 'TK', + 'TL', + 'TM', + 'TN', + 'TO', + 'TR', + 'TT', + 'TV', + 'TW', + 'TZ', + 'UA', + 'UG', + 'UM', + 'US', + 'UY', + 'UZ', + 'VA', + 'VC', + 'VE', + 'VG', + 'VI', + 'VN', + 'VU', + 'WF', + 'WS', + 'XA', + 'XB', + 'XK', + 'YE', + 'YT', + 'ZA', + 'ZM', + 'ZW', + ]; + + public function testGetRegions() + { + $this->assertSame(self::$territories, Regions::getRegionCodes()); + } + + /** + * @dataProvider provideLocales + */ + public function testGetNames($displayLocale) + { + $countries = array_keys(Regions::getNames($displayLocale)); + + sort($countries); + + $this->assertSame(self::$territories, $countries); + } + + public function testGetNamesDefaultLocale() + { + Locale::setDefault('de_AT'); + + $this->assertSame(Regions::getNames('de_AT'), Regions::getNames()); + } + + /** + * @dataProvider provideLocaleAliases + */ + public function testGetNamesSupportsAliases($alias, $ofLocale) + { + // Can't use assertSame(), because some aliases contain scripts with + // different collation (=order of output) than their aliased locale + // e.g. sr_Latn_ME => sr_ME + $this->assertEquals(Regions::getNames($ofLocale), Regions::getNames($alias)); + } + + /** + * @dataProvider provideLocales + */ + public function testGetName($displayLocale) + { + $names = Regions::getNames($displayLocale); + + foreach ($names as $country => $name) { + $this->assertSame($name, Regions::getName($country, $displayLocale)); + } + } + + /** + * @requires extension intl + */ + public function testLocaleAliasesAreLoaded() + { + \Locale::setDefault('zh_TW'); + $countryNameZhTw = Regions::getName('AD'); + + \Locale::setDefault('zh_Hant_TW'); + $countryNameHantZhTw = Regions::getName('AD'); + + \Locale::setDefault('zh'); + $countryNameZh = Regions::getName('AD'); + + $this->assertSame($countryNameZhTw, $countryNameHantZhTw, 'zh_TW is an alias to zh_Hant_TW'); + $this->assertNotSame($countryNameZh, $countryNameZhTw, 'zh_TW does not fall back to zh'); + } +} diff --git a/src/Symfony/Component/Intl/Tests/ResourceBundleTestCase.php b/src/Symfony/Component/Intl/Tests/ResourceBundleTestCase.php new file mode 100644 index 0000000000000..3e460985896c7 --- /dev/null +++ b/src/Symfony/Component/Intl/Tests/ResourceBundleTestCase.php @@ -0,0 +1,751 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Intl\Locale; + +abstract class ResourceBundleTestCase extends TestCase +{ + // Include the locales statically so that the data providers are decoupled + // from the Intl class. Otherwise tests will fail if the intl extension is + // not loaded, because it is NOT possible to skip the execution of data + // providers. + + private static $locales = [ + 'af', + 'af_NA', + 'af_ZA', + 'ak', + 'ak_GH', + 'am', + 'am_ET', + 'ar', + 'ar_001', + 'ar_AE', + 'ar_BH', + 'ar_DJ', + 'ar_DZ', + 'ar_EG', + 'ar_EH', + 'ar_ER', + 'ar_IL', + 'ar_IQ', + 'ar_JO', + 'ar_KM', + 'ar_KW', + 'ar_LB', + 'ar_LY', + 'ar_MA', + 'ar_MR', + 'ar_OM', + 'ar_PS', + 'ar_QA', + 'ar_SA', + 'ar_SD', + 'ar_SO', + 'ar_SS', + 'ar_SY', + 'ar_TD', + 'ar_TN', + 'ar_YE', + 'as', + 'as_IN', + 'az', + 'az_AZ', + 'az_Cyrl', + 'az_Cyrl_AZ', + 'az_Latn', + 'az_Latn_AZ', + 'be', + 'be_BY', + 'bg', + 'bg_BG', + 'bm', + 'bm_ML', + 'bn', + 'bn_BD', + 'bn_IN', + 'bo', + 'bo_CN', + 'bo_IN', + 'br', + 'br_FR', + 'bs', + 'bs_BA', + 'bs_Cyrl', + 'bs_Cyrl_BA', + 'bs_Latn', + 'bs_Latn_BA', + 'ca', + 'ca_AD', + 'ca_ES', + 'ca_FR', + 'ca_IT', + 'ce', + 'ce_RU', + 'cs', + 'cs_CZ', + 'cy', + 'cy_GB', + 'da', + 'da_DK', + 'da_GL', + 'de', + 'de_AT', + 'de_BE', + 'de_CH', + 'de_DE', + 'de_IT', + 'de_LI', + 'de_LU', + 'dz', + 'dz_BT', + 'ee', + 'ee_GH', + 'ee_TG', + 'el', + 'el_CY', + 'el_GR', + 'en', + 'en_001', + 'en_150', + 'en_AE', + 'en_AG', + 'en_AI', + 'en_AS', + 'en_AT', + 'en_AU', + 'en_BB', + 'en_BE', + 'en_BI', + 'en_BM', + 'en_BS', + 'en_BW', + 'en_BZ', + 'en_CA', + 'en_CC', + 'en_CH', + 'en_CK', + 'en_CM', + 'en_CX', + 'en_CY', + 'en_DE', + 'en_DG', + 'en_DK', + 'en_DM', + 'en_ER', + 'en_FI', + 'en_FJ', + 'en_FK', + 'en_FM', + 'en_GB', + 'en_GD', + 'en_GG', + 'en_GH', + 'en_GI', + 'en_GM', + 'en_GU', + 'en_GY', + 'en_HK', + 'en_IE', + 'en_IL', + 'en_IM', + 'en_IN', + 'en_IO', + 'en_JE', + 'en_JM', + 'en_KE', + 'en_KI', + 'en_KN', + 'en_KY', + 'en_LC', + 'en_LR', + 'en_LS', + 'en_MG', + 'en_MH', + 'en_MO', + 'en_MP', + 'en_MS', + 'en_MT', + 'en_MU', + 'en_MW', + 'en_MY', + 'en_NA', + 'en_NF', + 'en_NG', + 'en_NH', + 'en_NL', + 'en_NR', + 'en_NU', + 'en_NZ', + 'en_PG', + 'en_PH', + 'en_PK', + 'en_PN', + 'en_PR', + 'en_PW', + 'en_RH', + 'en_RW', + 'en_SB', + 'en_SC', + 'en_SD', + 'en_SE', + 'en_SG', + 'en_SH', + 'en_SI', + 'en_SL', + 'en_SS', + 'en_SX', + 'en_SZ', + 'en_TC', + 'en_TK', + 'en_TO', + 'en_TT', + 'en_TV', + 'en_TZ', + 'en_UG', + 'en_UM', + 'en_US', + 'en_US_POSIX', + 'en_VC', + 'en_VG', + 'en_VI', + 'en_VU', + 'en_WS', + 'en_ZA', + 'en_ZM', + 'en_ZW', + 'eo', + 'eo_001', + 'es', + 'es_419', + 'es_AR', + 'es_BO', + 'es_BR', + 'es_BZ', + 'es_CL', + 'es_CO', + 'es_CR', + 'es_CU', + 'es_DO', + 'es_EA', + 'es_EC', + 'es_ES', + 'es_GQ', + 'es_GT', + 'es_HN', + 'es_IC', + 'es_MX', + 'es_NI', + 'es_PA', + 'es_PE', + 'es_PH', + 'es_PR', + 'es_PY', + 'es_SV', + 'es_US', + 'es_UY', + 'es_VE', + 'et', + 'et_EE', + 'eu', + 'eu_ES', + 'fa', + 'fa_AF', + 'fa_IR', + 'ff', + 'ff_CM', + 'ff_GN', + 'ff_Latn', + 'ff_Latn_BF', + 'ff_Latn_CM', + 'ff_Latn_GH', + 'ff_Latn_GM', + 'ff_Latn_GN', + 'ff_Latn_GW', + 'ff_Latn_LR', + 'ff_Latn_MR', + 'ff_Latn_NE', + 'ff_Latn_NG', + 'ff_Latn_SL', + 'ff_Latn_SN', + 'ff_MR', + 'ff_SN', + 'fi', + 'fi_FI', + 'fo', + 'fo_DK', + 'fo_FO', + 'fr', + 'fr_BE', + 'fr_BF', + 'fr_BI', + 'fr_BJ', + 'fr_BL', + 'fr_CA', + 'fr_CD', + 'fr_CF', + 'fr_CG', + 'fr_CH', + 'fr_CI', + 'fr_CM', + 'fr_DJ', + 'fr_DZ', + 'fr_FR', + 'fr_GA', + 'fr_GF', + 'fr_GN', + 'fr_GP', + 'fr_GQ', + 'fr_HT', + 'fr_KM', + 'fr_LU', + 'fr_MA', + 'fr_MC', + 'fr_MF', + 'fr_MG', + 'fr_ML', + 'fr_MQ', + 'fr_MR', + 'fr_MU', + 'fr_NC', + 'fr_NE', + 'fr_PF', + 'fr_PM', + 'fr_RE', + 'fr_RW', + 'fr_SC', + 'fr_SN', + 'fr_SY', + 'fr_TD', + 'fr_TG', + 'fr_TN', + 'fr_VU', + 'fr_WF', + 'fr_YT', + 'fy', + 'fy_NL', + 'ga', + 'ga_IE', + 'gd', + 'gd_GB', + 'gl', + 'gl_ES', + 'gu', + 'gu_IN', + 'gv', + 'gv_IM', + 'ha', + 'ha_GH', + 'ha_NE', + 'ha_NG', + 'he', + 'he_IL', + 'hi', + 'hi_IN', + 'hr', + 'hr_BA', + 'hr_HR', + 'hu', + 'hu_HU', + 'hy', + 'hy_AM', + 'ia', + 'ia_001', + 'id', + 'id_ID', + 'ig', + 'ig_NG', + 'ii', + 'ii_CN', + 'in', + 'in_ID', + 'is', + 'is_IS', + 'it', + 'it_CH', + 'it_IT', + 'it_SM', + 'it_VA', + 'iw', + 'iw_IL', + 'ja', + 'ja_JP', + 'ja_JP_TRADITIONAL', + 'jv', + 'jv_ID', + 'ka', + 'ka_GE', + 'ki', + 'ki_KE', + 'kk', + 'kk_KZ', + 'kl', + 'kl_GL', + 'km', + 'km_KH', + 'kn', + 'kn_IN', + 'ko', + 'ko_KP', + 'ko_KR', + 'ks', + 'ks_IN', + 'ku', + 'ku_TR', + 'kw', + 'kw_GB', + 'ky', + 'ky_KG', + 'lb', + 'lb_LU', + 'lg', + 'lg_UG', + 'ln', + 'ln_AO', + 'ln_CD', + 'ln_CF', + 'ln_CG', + 'lo', + 'lo_LA', + 'lt', + 'lt_LT', + 'lu', + 'lu_CD', + 'lv', + 'lv_LV', + 'mg', + 'mg_MG', + 'mi', + 'mi_NZ', + 'mk', + 'mk_MK', + 'ml', + 'ml_IN', + 'mn', + 'mn_MN', + 'mo', + 'mr', + 'mr_IN', + 'ms', + 'ms_BN', + 'ms_MY', + 'ms_SG', + 'mt', + 'mt_MT', + 'my', + 'my_MM', + 'nb', + 'nb_NO', + 'nb_SJ', + 'nd', + 'nd_ZW', + 'ne', + 'ne_IN', + 'ne_NP', + 'nl', + 'nl_AW', + 'nl_BE', + 'nl_BQ', + 'nl_CW', + 'nl_NL', + 'nl_SR', + 'nl_SX', + 'nn', + 'nn_NO', + 'no', + 'no_NO', + 'no_NO_NY', + 'om', + 'om_ET', + 'om_KE', + 'or', + 'or_IN', + 'os', + 'os_GE', + 'os_RU', + 'pa', + 'pa_Arab', + 'pa_Arab_PK', + 'pa_Guru', + 'pa_Guru_IN', + 'pa_IN', + 'pa_PK', + 'pl', + 'pl_PL', + 'ps', + 'ps_AF', + 'ps_PK', + 'pt', + 'pt_AO', + 'pt_BR', + 'pt_CH', + 'pt_CV', + 'pt_GQ', + 'pt_GW', + 'pt_LU', + 'pt_MO', + 'pt_MZ', + 'pt_PT', + 'pt_ST', + 'pt_TL', + 'qu', + 'qu_BO', + 'qu_EC', + 'qu_PE', + 'rm', + 'rm_CH', + 'rn', + 'rn_BI', + 'ro', + 'ro_MD', + 'ro_RO', + 'ru', + 'ru_BY', + 'ru_KG', + 'ru_KZ', + 'ru_MD', + 'ru_RU', + 'ru_UA', + 'rw', + 'rw_RW', + 'sd', + 'sd_PK', + 'se', + 'se_FI', + 'se_NO', + 'se_SE', + 'sg', + 'sg_CF', + 'sh', + 'sh_BA', + 'sh_CS', + 'sh_YU', + 'si', + 'si_LK', + 'sk', + 'sk_SK', + 'sl', + 'sl_SI', + 'sn', + 'sn_ZW', + 'so', + 'so_DJ', + 'so_ET', + 'so_KE', + 'so_SO', + 'sq', + 'sq_AL', + 'sq_MK', + 'sq_XK', + 'sr', + 'sr_BA', + 'sr_CS', + 'sr_Cyrl', + 'sr_Cyrl_BA', + 'sr_Cyrl_CS', + 'sr_Cyrl_ME', + 'sr_Cyrl_RS', + 'sr_Cyrl_XK', + 'sr_Cyrl_YU', + 'sr_Latn', + 'sr_Latn_BA', + 'sr_Latn_CS', + 'sr_Latn_ME', + 'sr_Latn_RS', + 'sr_Latn_XK', + 'sr_Latn_YU', + 'sr_ME', + 'sr_RS', + 'sr_XK', + 'sr_YU', + 'sv', + 'sv_AX', + 'sv_FI', + 'sv_SE', + 'sw', + 'sw_CD', + 'sw_KE', + 'sw_TZ', + 'sw_UG', + 'ta', + 'ta_IN', + 'ta_LK', + 'ta_MY', + 'ta_SG', + 'te', + 'te_IN', + 'tg', + 'tg_TJ', + 'th', + 'th_TH', + 'th_TH_TRADITIONAL', + 'ti', + 'ti_ER', + 'ti_ET', + 'tk', + 'tk_TM', + 'tl', + 'tl_PH', + 'to', + 'to_TO', + 'tr', + 'tr_CY', + 'tr_TR', + 'tt', + 'tt_RU', + 'ug', + 'ug_CN', + 'uk', + 'uk_UA', + 'ur', + 'ur_IN', + 'ur_PK', + 'uz', + 'uz_AF', + 'uz_Arab', + 'uz_Arab_AF', + 'uz_Cyrl', + 'uz_Cyrl_UZ', + 'uz_Latn', + 'uz_Latn_UZ', + 'uz_UZ', + 'vi', + 'vi_VN', + 'wo', + 'wo_SN', + 'xh', + 'xh_ZA', + 'yi', + 'yi_001', + 'yo', + 'yo_BJ', + 'yo_NG', + 'zh', + 'zh_CN', + 'zh_HK', + 'zh_Hans', + 'zh_Hans_CN', + 'zh_Hans_HK', + 'zh_Hans_MO', + 'zh_Hans_SG', + 'zh_Hant', + 'zh_Hant_HK', + 'zh_Hant_MO', + 'zh_Hant_TW', + 'zh_MO', + 'zh_SG', + 'zh_TW', + 'zu', + 'zu_ZA', + ]; + + private static $localeAliases = [ + 'az_AZ' => 'az_Latn_AZ', + 'bs_BA' => 'bs_Latn_BA', + 'en_NH' => 'en_VU', + 'en_RH' => 'en_ZW', + 'ff_CM' => 'ff_Latn_CM', + 'ff_GN' => 'ff_Latn_GN', + 'ff_MR' => 'ff_Latn_MR', + 'ff_SN' => 'ff_Latn_SN', + 'in' => 'id', + 'in_ID' => 'id_ID', + 'iw' => 'he', + 'iw_IL' => 'he_IL', + 'mo' => 'ro', + 'no' => 'nb', + 'no_NO' => 'nb_NO', + 'no_NO_NY' => 'nn_NO', + 'pa_IN' => 'pa_Guru_IN', + 'pa_PK' => 'pa_Arab_PK', + 'sh' => 'sr_Latn', + 'sh_BA' => 'sr_Latn_BA', + 'sh_CS' => 'sr_Latn_RS', + 'sh_YU' => 'sr_Latn_RS', + 'sr_BA' => 'sr_Cyrl_BA', + 'sr_CS' => 'sr_Cyrl_RS', + 'sr_Cyrl_CS' => 'sr_Cyrl_RS', + 'sr_Cyrl_YU' => 'sr_Cyrl_RS', + 'sr_Latn_CS' => 'sr_Latn_RS', + 'sr_Latn_YU' => 'sr_Latn_RS', + 'sr_ME' => 'sr_Latn_ME', + 'sr_RS' => 'sr_Cyrl_RS', + 'sr_XK' => 'sr_Cyrl_XK', + 'sr_YU' => 'sr_Cyrl_RS', + 'tl' => 'fil', + 'tl_PH' => 'fil_PH', + 'uz_AF' => 'uz_Arab_AF', + 'uz_UZ' => 'uz_Latn_UZ', + 'zh_CN' => 'zh_Hans_CN', + 'zh_HK' => 'zh_Hant_HK', + 'zh_MO' => 'zh_Hant_MO', + 'zh_SG' => 'zh_Hans_SG', + 'zh_TW' => 'zh_Hant_TW', + ]; + + private static $rootLocales; + + protected function setUp() + { + Locale::setDefault('en'); + Locale::setDefaultFallback('en'); + } + + public function provideLocales() + { + return array_map( + function ($locale) { return [$locale]; }, + $this->getLocales() + ); + } + + public function provideLocaleAliases() + { + return array_map( + function ($alias, $ofLocale) { return [$alias, $ofLocale]; }, + array_keys($this->getLocaleAliases()), + $this->getLocaleAliases() + ); + } + + public function provideRootLocales() + { + return array_map( + function ($locale) { return [$locale]; }, + $this->getRootLocales() + ); + } + + protected function getLocales() + { + return self::$locales; + } + + protected function getLocaleAliases() + { + return self::$localeAliases; + } + + protected function getRootLocales() + { + if (null === self::$rootLocales) { + self::$rootLocales = array_filter($this->getLocales(), function ($locale) { + // no locales for which fallback is possible (e.g "en_GB") + return false === strpos($locale, '_'); + }); + } + + return self::$rootLocales; + } +} diff --git a/src/Symfony/Component/Intl/Tests/ScriptsTest.php b/src/Symfony/Component/Intl/Tests/ScriptsTest.php new file mode 100644 index 0000000000000..5b404fda85aaa --- /dev/null +++ b/src/Symfony/Component/Intl/Tests/ScriptsTest.php @@ -0,0 +1,277 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl\Tests; + +use Symfony\Component\Intl\Locale; +use Symfony\Component\Intl\Scripts; + +/** + * @group intl-data + */ +class ScriptsTest extends ResourceBundleTestCase +{ + // The below arrays document the state of the ICU data bundled with this package. + + protected static $scripts = [ + 'Adlm', + 'Afak', + 'Aghb', + 'Ahom', + 'Arab', + 'Armi', + 'Armn', + 'Avst', + 'Bali', + 'Bamu', + 'Bass', + 'Batk', + 'Beng', + 'Bhks', + 'Blis', + 'Bopo', + 'Brah', + 'Brai', + 'Bugi', + 'Buhd', + 'Cakm', + 'Cans', + 'Cari', + 'Cham', + 'Cher', + 'Cirt', + 'Copt', + 'Cprt', + 'Cyrl', + 'Cyrs', + 'Deva', + 'Dogr', + 'Dsrt', + 'Dupl', + 'Egyd', + 'Egyh', + 'Egyp', + 'Elba', + 'Elym', + 'Ethi', + 'Geok', + 'Geor', + 'Glag', + 'Gong', + 'Gonm', + 'Goth', + 'Gran', + 'Grek', + 'Gujr', + 'Guru', + 'Hanb', + 'Hang', + 'Hani', + 'Hano', + 'Hans', + 'Hant', + 'Hatr', + 'Hebr', + 'Hira', + 'Hluw', + 'Hmng', + 'Hmnp', + 'Hrkt', + 'Hung', + 'Inds', + 'Ital', + 'Jamo', + 'Java', + 'Jpan', + 'Jurc', + 'Kali', + 'Kana', + 'Khar', + 'Khmr', + 'Khoj', + 'Knda', + 'Kore', + 'Kpel', + 'Kthi', + 'Lana', + 'Laoo', + 'Latf', + 'Latg', + 'Latn', + 'Lepc', + 'Limb', + 'Lina', + 'Linb', + 'Lisu', + 'Loma', + 'Lyci', + 'Lydi', + 'Mahj', + 'Maka', + 'Mand', + 'Mani', + 'Marc', + 'Maya', + 'Medf', + 'Mend', + 'Merc', + 'Mero', + 'Mlym', + 'Modi', + 'Mong', + 'Moon', + 'Mroo', + 'Mtei', + 'Mult', + 'Mymr', + 'Nand', + 'Narb', + 'Nbat', + 'Newa', + 'Nkgb', + 'Nkoo', + 'Nshu', + 'Ogam', + 'Olck', + 'Orkh', + 'Orya', + 'Osge', + 'Osma', + 'Palm', + 'Pauc', + 'Perm', + 'Phag', + 'Phli', + 'Phlp', + 'Phlv', + 'Phnx', + 'Plrd', + 'Prti', + 'Qaag', + 'Rjng', + 'Rohg', + 'Roro', + 'Runr', + 'Samr', + 'Sara', + 'Sarb', + 'Saur', + 'Sgnw', + 'Shaw', + 'Shrd', + 'Sidd', + 'Sind', + 'Sinh', + 'Sogd', + 'Sogo', + 'Sora', + 'Soyo', + 'Sund', + 'Sylo', + 'Syrc', + 'Syre', + 'Syrj', + 'Syrn', + 'Tagb', + 'Takr', + 'Tale', + 'Talu', + 'Taml', + 'Tang', + 'Tavt', + 'Telu', + 'Teng', + 'Tfng', + 'Tglg', + 'Thaa', + 'Thai', + 'Tibt', + 'Tirh', + 'Ugar', + 'Vaii', + 'Visp', + 'Wara', + 'Wcho', + 'Wole', + 'Xpeo', + 'Xsux', + 'Yiii', + 'Zanb', + 'Zinh', + 'Zmth', + 'Zsye', + 'Zsym', + 'Zxxx', + 'Zyyy', + 'Zzzz', + ]; + + public function testGetScripts() + { + $this->assertSame(self::$scripts, Scripts::getScriptCodes()); + } + + /** + * @dataProvider provideLocales + */ + public function testGetNames($displayLocale) + { + $scripts = array_keys(Scripts::getNames($displayLocale)); + + sort($scripts); + + // We can't assert on exact list of scripts, as there's too many variations between locales. + // The best we can do is to make sure getNames() returns a subset of what getScripts() returns. + $this->assertNotEmpty($scripts); + $this->assertEmpty(array_diff($scripts, self::$scripts)); + } + + public function testGetNamesDefaultLocale() + { + Locale::setDefault('de_AT'); + + $this->assertSame(Scripts::getNames('de_AT'), Scripts::getNames()); + } + + /** + * @dataProvider provideLocaleAliases + */ + public function testGetNamesSupportsAliases($alias, $ofLocale) + { + // Can't use assertSame(), because some aliases contain scripts with + // different collation (=order of output) than their aliased locale + // e.g. sr_Latn_ME => sr_ME + $this->assertEquals(Scripts::getNames($ofLocale), Scripts::getNames($alias)); + } + + /** + * @dataProvider provideLocales + */ + public function testGetName($displayLocale) + { + $names = Scripts::getNames($displayLocale); + + foreach ($names as $script => $name) { + $this->assertSame($name, Scripts::getName($script, $displayLocale)); + } + } + + public function testGetNameDefaultLocale() + { + Locale::setDefault('de_AT'); + + $names = Scripts::getNames('de_AT'); + + foreach ($names as $script => $name) { + $this->assertSame($name, Scripts::getName($script)); + } + } +} diff --git a/src/Symfony/Component/Validator/Constraints/Bic.php b/src/Symfony/Component/Validator/Constraints/Bic.php index c0eeade9a9d48..bd782f4c38934 100644 --- a/src/Symfony/Component/Validator/Constraints/Bic.php +++ b/src/Symfony/Component/Validator/Constraints/Bic.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Regions; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -47,7 +47,7 @@ class Bic extends Constraint public function __construct($options = null) { - if (!class_exists(Intl::class)) { + if (!class_exists(Regions::class)) { // throw new LogicException(sprintf('The "symfony/intl" component is required to use the "%s" constraint.', __CLASS__)); @trigger_error(sprintf('Using the "%s" constraint without the "symfony/intl" component installed is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED); } diff --git a/src/Symfony/Component/Validator/Constraints/BicValidator.php b/src/Symfony/Component/Validator/Constraints/BicValidator.php index 3036d200e0668..3bbed7bfd0f20 100644 --- a/src/Symfony/Component/Validator/Constraints/BicValidator.php +++ b/src/Symfony/Component/Validator/Constraints/BicValidator.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Regions; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessor; @@ -105,8 +105,8 @@ public function validate($value, Constraint $constraint) } // @deprecated since Symfony 4.2, will throw in 5.0 - if (class_exists(Intl::class)) { - $validCountryCode = isset(Intl::getRegionBundle()->getCountryNames()[substr($canonicalize, 4, 2)]); + if (class_exists(Regions::class)) { + $validCountryCode = Regions::exists(substr($canonicalize, 4, 2)); } else { $validCountryCode = ctype_alpha(substr($canonicalize, 4, 2)); // throw new LogicException('The "symfony/intl" component is required to use the Bic constraint.'); diff --git a/src/Symfony/Component/Validator/Constraints/Country.php b/src/Symfony/Component/Validator/Constraints/Country.php index 09e1996d5bcb8..adedb665b6467 100644 --- a/src/Symfony/Component/Validator/Constraints/Country.php +++ b/src/Symfony/Component/Validator/Constraints/Country.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Regions; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\LogicException; @@ -33,7 +33,7 @@ class Country extends Constraint public function __construct($options = null) { - if (!class_exists(Intl::class)) { + if (!class_exists(Regions::class)) { // throw new LogicException(sprintf('The "symfony/intl" component is required to use the "%s" constraint.', __CLASS__)); @trigger_error(sprintf('Using the "%s" constraint without the "symfony/intl" component installed is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED); } diff --git a/src/Symfony/Component/Validator/Constraints/CountryValidator.php b/src/Symfony/Component/Validator/Constraints/CountryValidator.php index ad5dc36a9ab54..057420f7bcbed 100644 --- a/src/Symfony/Component/Validator/Constraints/CountryValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CountryValidator.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Regions; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\LogicException; @@ -42,14 +42,13 @@ public function validate($value, Constraint $constraint) throw new UnexpectedValueException($value, 'string'); } - if (!class_exists(Intl::class)) { + if (!class_exists(Regions::class)) { throw new LogicException('The "symfony/intl" component is required to use the Country constraint.'); } $value = (string) $value; - $countries = Intl::getRegionBundle()->getCountryNames(); - if (!isset($countries[$value])) { + if (!Regions::exists($value)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Country::NO_SUCH_COUNTRY_ERROR) diff --git a/src/Symfony/Component/Validator/Constraints/Currency.php b/src/Symfony/Component/Validator/Constraints/Currency.php index 4f9d7d26fc444..73ea29488f561 100644 --- a/src/Symfony/Component/Validator/Constraints/Currency.php +++ b/src/Symfony/Component/Validator/Constraints/Currency.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Currencies; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\LogicException; @@ -34,7 +34,7 @@ class Currency extends Constraint public function __construct($options = null) { - if (!class_exists(Intl::class)) { + if (!class_exists(Currencies::class)) { // throw new LogicException(sprintf('The "symfony/intl" component is required to use the "%s" constraint.', __CLASS__)); @trigger_error(sprintf('Using the "%s" constraint without the "symfony/intl" component installed is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED); } diff --git a/src/Symfony/Component/Validator/Constraints/CurrencyValidator.php b/src/Symfony/Component/Validator/Constraints/CurrencyValidator.php index 44e5df246cb89..cc25aa738e32d 100644 --- a/src/Symfony/Component/Validator/Constraints/CurrencyValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CurrencyValidator.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Currencies; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\LogicException; @@ -43,14 +43,13 @@ public function validate($value, Constraint $constraint) throw new UnexpectedValueException($value, 'string'); } - if (!class_exists(Intl::class)) { + if (!class_exists(Currencies::class)) { throw new LogicException('The "symfony/intl" component is required to use the Currency constraint.'); } $value = (string) $value; - $currencies = Intl::getCurrencyBundle()->getCurrencyNames(); - if (!isset($currencies[$value])) { + if (!Currencies::exists($value)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Currency::NO_SUCH_CURRENCY_ERROR) diff --git a/src/Symfony/Component/Validator/Constraints/Language.php b/src/Symfony/Component/Validator/Constraints/Language.php index ce01bba15f09f..47b9389557b50 100644 --- a/src/Symfony/Component/Validator/Constraints/Language.php +++ b/src/Symfony/Component/Validator/Constraints/Language.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Languages; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\LogicException; @@ -33,7 +33,7 @@ class Language extends Constraint public function __construct($options = null) { - if (!class_exists(Intl::class)) { + if (!class_exists(Languages::class)) { // throw new LogicException(sprintf('The "symfony/intl" component is required to use the "%s" constraint.', __CLASS__)); @trigger_error(sprintf('Using the "%s" constraint without the "symfony/intl" component installed is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED); } diff --git a/src/Symfony/Component/Validator/Constraints/LanguageValidator.php b/src/Symfony/Component/Validator/Constraints/LanguageValidator.php index 22ddb0fe53459..b193ceda84107 100644 --- a/src/Symfony/Component/Validator/Constraints/LanguageValidator.php +++ b/src/Symfony/Component/Validator/Constraints/LanguageValidator.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Languages; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\LogicException; @@ -42,14 +42,13 @@ public function validate($value, Constraint $constraint) throw new UnexpectedValueException($value, 'string'); } - if (!class_exists(Intl::class)) { + if (!class_exists(Languages::class)) { throw new LogicException('The "symfony/intl" component is required to use the Language constraint.'); } $value = (string) $value; - $languages = Intl::getLanguageBundle()->getLanguageNames(); - if (!isset($languages[$value])) { + if (!Languages::exists($value)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Language::NO_SUCH_LANGUAGE_ERROR) diff --git a/src/Symfony/Component/Validator/Constraints/Locale.php b/src/Symfony/Component/Validator/Constraints/Locale.php index 0e4ccf69ce319..d56db7cf212f7 100644 --- a/src/Symfony/Component/Validator/Constraints/Locale.php +++ b/src/Symfony/Component/Validator/Constraints/Locale.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Locales; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\LogicException; @@ -38,7 +38,7 @@ public function __construct($options = null) @trigger_error('The "canonicalize" option with value "false" is deprecated since Symfony 4.1, set it to "true" instead.', E_USER_DEPRECATED); } - if (!class_exists(Intl::class)) { + if (!class_exists(Locales::class)) { // throw new LogicException(sprintf('The "symfony/intl" component is required to use the "%s" constraint.', __CLASS__)); @trigger_error(sprintf('Using the "%s" constraint without the "symfony/intl" component installed is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED); } diff --git a/src/Symfony/Component/Validator/Constraints/LocaleValidator.php b/src/Symfony/Component/Validator/Constraints/LocaleValidator.php index d4bca35a70375..244d0f554ba09 100644 --- a/src/Symfony/Component/Validator/Constraints/LocaleValidator.php +++ b/src/Symfony/Component/Validator/Constraints/LocaleValidator.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; +use Symfony\Component\Intl\Locales; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; @@ -46,10 +47,8 @@ public function validate($value, Constraint $constraint) if ($constraint->canonicalize) { $value = \Locale::canonicalize($value); } - $localeBundle = Intl::getLocaleBundle(); - $locales = $localeBundle->getLocaleNames(); - if (!isset($locales[$value]) && !\in_array($value, $localeBundle->getAliases(), true)) { + if (!Locales::exists($value) && !\in_array($value, Locales::getAliases(), true)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($inputValue)) ->setCode(Locale::NO_SUCH_LOCALE_ERROR) diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 9813a88563afc..b6eae402a8009 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -26,7 +26,7 @@ "symfony/http-foundation": "~4.1", "symfony/http-kernel": "~3.4|~4.0", "symfony/var-dumper": "~3.4|~4.0", - "symfony/intl": "~4.1", + "symfony/intl": "^4.3", "symfony/yaml": "~3.4|~4.0", "symfony/config": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", @@ -43,7 +43,7 @@ "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", "symfony/dependency-injection": "<3.4", "symfony/http-kernel": "<3.4", - "symfony/intl": "<4.1", + "symfony/intl": "<4.3", "symfony/translation": "<4.2", "symfony/yaml": "<3.4" },