diff --git a/src/Charcoal/Translator/LocalesManager.php b/src/Charcoal/Translator/LocalesManager.php index 01b7fb4..a0e77b4 100644 --- a/src/Charcoal/Translator/LocalesManager.php +++ b/src/Charcoal/Translator/LocalesManager.php @@ -31,14 +31,14 @@ class LocalesManager * * @var string */ - private $defaultLocale; + private $defaultLanguage; /** * Language code for the current locale. * * @var string|null */ - private $currentLocale; + private $currentLanguage; /** * Create the Locales Manager with locales and optional options. @@ -58,25 +58,12 @@ class LocalesManager public function __construct(array $data) { $this->setLocales($data['locales']); - $this->languages = array_keys($this->locales); - - if (isset($data['default_language'])) { - if (!$this->hasLocale($data['default_language'])) { - $lang = $data['default_language']; - if (!is_string($lang)) { - $lang = is_object($lang) ? get_class($lang) : gettype($lang); - } - - throw new InvalidArgumentException(sprintf( - 'Unsupported default language; must be one of "%s", received %s', - implode(', ', $this->languages), - $lang - )); - } - $this->defaultLocale = $data['default_language']; - } else { - $this->defaultLocale = $this->languages[0]; - } + + $default = isset($data['default_language']) ? $data['default_language'] : null; + $this->setDefaultLocale($default); + + $current = isset($data['current_language']) ? $data['current_language'] : null; + $this->setCurrentLocale($current); } /** @@ -99,6 +86,46 @@ public function availableLocales() return $this->languages; } + /** + * Set the default language. + * + * @param string|null $lang The default language code. + * If NULL, the first language is assigned. + * @throws InvalidArgumentException If the language is invalid. + * @return void + */ + private function setDefaultLocale($lang) + { + if ($lang === null) { + $this->defaultLanguage = $this->languages[0]; + return; + } + + if (!$this->hasLocale($lang)) { + if (!is_string($lang)) { + $lang = is_object($lang) ? get_class($lang) : gettype($lang); + } + + throw new InvalidArgumentException(sprintf( + 'Unsupported default language; must be one of "%s", received "%s"', + implode(', ', $this->availableLocales()), + $lang + )); + } + + $this->defaultLanguage = $lang; + } + + /** + * Retrieve the default language. + * + * @return string + */ + public function defaultLocale() + { + return $this->defaultLanguage; + } + /** * Set the current language. * @@ -110,7 +137,7 @@ public function availableLocales() public function setCurrentLocale($lang) { if ($lang === null) { - $this->currentLocale = null; + $this->currentLanguage = null; return; } @@ -126,7 +153,7 @@ public function setCurrentLocale($lang) )); } - $this->currentLocale = $lang; + $this->currentLanguage = $lang; } /** @@ -136,10 +163,10 @@ public function setCurrentLocale($lang) */ public function currentLocale() { - if ($this->currentLocale === null) { - return $this->defaultLocale; + if ($this->currentLanguage === null) { + return $this->defaultLanguage; } - return $this->currentLocale; + return $this->currentLanguage; } /** @@ -150,7 +177,7 @@ public function currentLocale() */ public function hasLocale($lang) { - return in_array($lang, $this->availableLocales()); + return isset($this->locales[$lang]); } /** @@ -168,14 +195,16 @@ public function hasLocale($lang) private function setLocales(array $locales) { $this->locales = []; - foreach ($locales as $language => $locale) { + $this->languages = []; + foreach ($locales as $langCode => $locale) { if (isset($locale['active']) && !$locale['active']) { continue; } if (!isset($locale['locale'])) { - $locale['locale'] = $language; + $locale['locale'] = $langCode; } - $this->locales[$language] = $locale; + $this->locales[$langCode] = $locale; + $this->languages[] = $langCode; } if (empty($this->locales)) { throw new InvalidArgumentException( diff --git a/src/Charcoal/Translator/ServiceProvider/TranslatorServiceProvider.php b/src/Charcoal/Translator/ServiceProvider/TranslatorServiceProvider.php index f4e6d47..118b61b 100644 --- a/src/Charcoal/Translator/ServiceProvider/TranslatorServiceProvider.php +++ b/src/Charcoal/Translator/ServiceProvider/TranslatorServiceProvider.php @@ -84,6 +84,13 @@ private function registerLocales(Container $container) /** * Accepted language from the navigator. * + * Example with Accept-Language "zh-Hant-HK, fr-CH, fr;q=0.9, en;q=0.7": + * + * 1. zh-Hant-HK + * 2. fr-CH + * 3. fr + * 4. en + * * @param Container $container Pimple DI container. * @return string|null */ @@ -91,12 +98,22 @@ private function registerLocales(Container $container) if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { return null; } - $availableLanguages = $container['locales/available-languages']; - $acceptedLanguages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); - foreach ($acceptedLanguages as $acceptedLang) { + + /** + * Using data from configset instead of LocalesManager + * since the latter might need the browser language + * as the default language. + */ + $localesConfig = $container['locales/config']; + $supportedLocales = array_filter($localesConfig['languages'], function ($locale) { + return !(isset($locale['active']) && !$locale['active']); + }); + + $acceptableLanguages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + foreach ($acceptableLanguages as $acceptedLang) { $lang = explode(';', $acceptedLang); $lang = trim($lang[0]); - if (in_array($lang, $availableLanguages)) { + if (isset($supportedLocales[$lang])) { return $lang; } } @@ -107,6 +124,7 @@ private function registerLocales(Container $container) /** * List of fallback language codes for the translator. * + * @todo Use filtered "fallback_languages" from LocalesManager * @param Container $container Pimple DI container. * @return string[] */ @@ -122,8 +140,8 @@ private function registerLocales(Container $container) * @return string[] */ $container['locales/available-languages'] = function (Container $container) { - $localesConfig = $container['locales/config']; - return array_keys($localesConfig['languages']); + $manager = $container['locales/manager']; + return $manager->availableLocales(); }; /** @@ -133,13 +151,14 @@ private function registerLocales(Container $container) * @return array */ $container['locales/languages'] = function (Container $container) { - $localesConfig = $container['locales/config']; - return $localesConfig['languages']; + $manager = $container['locales/manager']; + return $manager->locales(); }; /** * Instance of the Locales Manager. * + * @todo Filter "fallback_languages" * @param Container $container Pimple DI container. * @return LocalesManager */ diff --git a/tests/Charcoal/Translator/LocalesManagerTest.php b/tests/Charcoal/Translator/LocalesManagerTest.php index 6dddde4..fd1a076 100644 --- a/tests/Charcoal/Translator/LocalesManagerTest.php +++ b/tests/Charcoal/Translator/LocalesManagerTest.php @@ -48,6 +48,7 @@ public function testConstructorWithDefaultLanguage() 'default_language' => 'bar' ]); $this->assertEquals('bar', $this->obj->currentLocale()); + $this->assertEquals('bar', $this->obj->defaultLocale()); } public function testConstructorDefaultLanguageWithInvalidType()