From 972a3306aee1ba40d8bd0caa3c9204a384135737 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 12 Feb 2018 16:55:55 +0100 Subject: [PATCH] [Intl] Add polyfill for Locale::canonicalize() --- src/Symfony/Component/Intl/Locale/Locale.php | 37 ++++++++++++++++++- .../Intl/Tests/Locale/LocaleTest.php | 11 ++++++ .../Validator/Constraints/LocaleValidator.php | 3 +- src/Symfony/Component/Validator/composer.json | 3 +- 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Intl/Locale/Locale.php b/src/Symfony/Component/Intl/Locale/Locale.php index 2aa9eb7b090a..053f1db56ffd 100644 --- a/src/Symfony/Component/Intl/Locale/Locale.php +++ b/src/Symfony/Component/Intl/Locale/Locale.php @@ -16,8 +16,8 @@ /** * Replacement for PHP's native {@link \Locale} class. * - * The only method supported in this class is {@link getDefault}. This method - * will always return "en". All other methods will throw an exception when used. + * The only methods supported in this class are `getDefault` and `canonicalize`. + * All other methods will throw an exception when used. * * @author Eriksen Costa * @author Bernhard Schussek @@ -57,6 +57,39 @@ public static function acceptFromHttp($header) throw new MethodNotImplementedException(__METHOD__); } + /** + * Returns a canonicalized locale string. + * + * This polyfill doesn't implement the full-spec algorithm. It only + * canonicalizes locale strings handled by the `LocaleBundle` class. + * + * @param string $locale + * + * @return string + */ + public static function canonicalize($locale) + { + $locale = (string) $locale; + + if ('' === $locale || '.' === $locale[0]) { + return self::getDefault(); + } + + if (!preg_match('/^([a-z]{2})[-_]([a-z]{2})(?:([a-z]{2})(?:[-_]([a-z]{2}))?)?(?:\..*)?$/i', $locale, $m)) { + return $locale; + } + + if (!empty($m[4])) { + return strtolower($m[1]).'_'.ucfirst(strtolower($m[2].$m[3])).'_'.strtoupper($m[4]); + } + + if (!empty($m[3])) { + return strtolower($m[1]).'_'.ucfirst(strtolower($m[2].$m[3])); + } + + return strtolower($m[1]).'_'.strtoupper($m[2]); + } + /** * Not supported. Returns a correctly ordered and delimited locale code. * diff --git a/src/Symfony/Component/Intl/Tests/Locale/LocaleTest.php b/src/Symfony/Component/Intl/Tests/Locale/LocaleTest.php index 5ee414a1c250..b0388620ba4b 100644 --- a/src/Symfony/Component/Intl/Tests/Locale/LocaleTest.php +++ b/src/Symfony/Component/Intl/Tests/Locale/LocaleTest.php @@ -21,6 +21,17 @@ public function testAcceptFromHttp() $this->call('acceptFromHttp', 'pt-br,en-us;q=0.7,en;q=0.5'); } + public function testCanonicalize() + { + $this->assertSame('en', $this->call('canonicalize', '')); + $this->assertSame('en', $this->call('canonicalize', '.utf8')); + $this->assertSame('fr_FR', $this->call('canonicalize', 'FR-fr')); + $this->assertSame('fr_FR', $this->call('canonicalize', 'FR-fr.utf8')); + $this->assertSame('uz_Latn', $this->call('canonicalize', 'UZ-lATN')); + $this->assertSame('uz_Cyrl_UZ', $this->call('canonicalize', 'UZ-cYRL-uz')); + $this->assertSame('123', $this->call('canonicalize', 123)); + } + /** * @expectedException \Symfony\Component\Intl\Exception\MethodNotImplementedException */ diff --git a/src/Symfony/Component/Validator/Constraints/LocaleValidator.php b/src/Symfony/Component/Validator/Constraints/LocaleValidator.php index 49783b6698e3..f3a3516a1151 100644 --- a/src/Symfony/Component/Validator/Constraints/LocaleValidator.php +++ b/src/Symfony/Component/Validator/Constraints/LocaleValidator.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; -use Symfony\Component\Intl\Locale as IntlLocale; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; @@ -43,7 +42,7 @@ public function validate($value, Constraint $constraint) $value = (string) $value; if ($constraint->canonicalize) { - $value = IntlLocale::canonicalize($value); + $value = \Locale::canonicalize($value); } $localeBundle = Intl::getLocaleBundle(); $locales = $localeBundle->getLocaleNames(); diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 2e44519c2776..7e7ce9df17ed 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -24,7 +24,7 @@ "symfony/http-foundation": "~4.1", "symfony/http-kernel": "~3.4|~4.0", "symfony/var-dumper": "~3.4|~4.0", - "symfony/intl": "~3.4|~4.0", + "symfony/intl": "~4.1", "symfony/yaml": "~3.4|~4.0", "symfony/config": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", @@ -39,6 +39,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/yaml": "<3.4" }, "suggest": {