diff --git a/readme.md b/readme.md index 351ec8b..355540e 100644 --- a/readme.md +++ b/readme.md @@ -307,7 +307,7 @@ $germany->{'name:de'} // 'Deutschland' If you want to fallback to a default translation when a translation has not been found, enable this in the configuration using the `use_fallback` key. And to select the default locale, use the `fallback_locale` key. -Example: +Configuration example: ```php return [ @@ -327,6 +327,40 @@ class Country { } ``` +#### Country based fallback + +Since version v5.3 it is possible to use country based locales. For example, you can have the following locales: + +- English: `en` +- Spanish: `es` +- Mexican Spanish: `es-MX` +- Colombian Spanish: `es-CO` + +To configuration for these locales looks like this: + +```php + 'locales' => [ + 'en', + 'es' => [ + 'MX', + 'CO', + ], + ]; +``` + +We can also configure the "glue" between the language and country. If for instance we prefer the format `es_MX` instead of `es-MX`, +the configuration should look like this: + +```php + 'locale_separator' => '_', +``` + +What applies for the fallback of the locales using the `en-MX` format? + +Let's say our fallback locale is `en`. Now, when we try to fetch from the database the translation for the +locale `es-MX` but it doesn't exist, we won't get as fallback the translation for `en`. Translatable will use as a +fallback `es` (the first part of `es-MX`) and only if nothing is found, the translation for `en` is returned. + ## FAQ #### I need some example code! diff --git a/src/Translatable/Translatable.php b/src/Translatable/Translatable.php index af38bd9..12b2345 100644 --- a/src/Translatable/Translatable.php +++ b/src/Translatable/Translatable.php @@ -55,16 +55,16 @@ public function translateOrNew($locale) public function getTranslation($locale = null, $withFallback = null) { $locale = $locale ?: $this->locale(); - $withFallback = $withFallback === null ? $this->useFallback() : $withFallback; + $fallbackLocale = $this->getFallbackLocale($locale); if ($this->getTranslationByLocaleKey($locale)) { $translation = $this->getTranslationByLocaleKey($locale); } elseif ($withFallback - && $this->getFallbackLocale() - && $this->getTranslationByLocaleKey($this->getFallbackLocale()) + && $fallbackLocale + && $this->getTranslationByLocaleKey($fallbackLocale) ) { - $translation = $this->getTranslationByLocaleKey($this->getFallbackLocale()); + $translation = $this->getTranslationByLocaleKey($fallbackLocale); } else { $translation = null; } @@ -266,13 +266,43 @@ private function getTranslationByLocaleKey($key) } /** + * @param null $locale + * * @return string */ - private function getFallbackLocale() + private function getFallbackLocale($locale = null) { + if ($locale && $this->isLocaleCountryBased($locale)) { + if ($fallback = $this->getLanguageFromCountryBasedLocale($locale)) { + return $fallback; + } + } + return App::make('config')->get('translatable.fallback_locale'); } + /** + * @param $locale + * + * @return bool + */ + private function isLocaleCountryBased($locale) + { + return strpos($locale, $this->getLocaleSeparator()) !== false; + } + + /** + * @param $locale + * + * @return string + */ + private function getLanguageFromCountryBasedLocale($locale) + { + $parts = explode($this->getLocaleSeparator(), $locale); + + return array_get($parts, 0); + } + /** * @return bool|null */ diff --git a/tests/TranslatableTest.php b/tests/TranslatableTest.php index 91b36fd..c8fff0f 100644 --- a/tests/TranslatableTest.php +++ b/tests/TranslatableTest.php @@ -395,4 +395,20 @@ public function test_locale_separator_can_be_configured() $this->assertSame('Chips', $frenchFries->getTranslation('en_GB')->name); } + public function test_fallback_for_country_based_locales() + { + $this->app->config->set('translatable.use_fallback', true); + $this->app->config->set('translatable.fallback_locale', 'fr'); + $this->app->config->set('translatable.locales', ['en' => ['US', 'GB'], 'fr']); + $this->app->config->set('translatable.locale_separator', '-'); + $data = [ + 'id' => 1, + 'fr' => ['name' => 'frites'], + 'en-GB' => ['name' => 'chips'], + 'en' => ['name' => 'french fries'], + ]; + Food::create($data); + $fries = Food::find(1); + $this->assertSame('french fries', $fries->getTranslation('en-US')->name); + } }