From 55b1cd49aa45b569de5789e4cf47aece9e26969f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruan=20P=C3=A9pe?= Date: Wed, 22 Jul 2020 00:12:40 -0300 Subject: [PATCH 1/4] Fallback locale gide at readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 000d16f..ca14e1f 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ The configuration options are: - **supportedLocales** Languages of your app (Default: English & Spanish). - **useAcceptLanguageHeader** If true, then automatically detect language from browser. + - **handleFallbackLocale** Manage fallback language. - **hideDefaultLocaleInURL** If true, then do not show default locale in url. - **localesOrder** Sort languages in custom order. - **localesMapping** Rename url locales. From 05c1039c3efade5ff209349495d30ab78899c0aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruan=20P=C3=A9pe?= Date: Wed, 22 Jul 2020 00:14:18 -0300 Subject: [PATCH 2/4] Fallback locale at config --- src/config/config.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/config/config.php b/src/config/config.php index c04a302..f06c50d 100644 --- a/src/config/config.php +++ b/src/config/config.php @@ -311,6 +311,14 @@ // If false, system will take app.php locale attribute 'useAcceptLanguageHeader' => true, + // Handle the locale used when translation key don't match result at current locale + // + // Valid options are + // - false (Not handle fallback locale and use app.fallback_locale) + // - 'related' (Use current locale without country code as fallback locale if it is in supported locales. e.g "en-US" will use "en", "pt-BR" will use "pt") + // - 'header' (Use the first language from browser as fallback locale if it is not equals the app locale, else use the second one) + 'handleFallbackLocale' => false, + // If `hideDefaultLocaleInURL` is true, then a url without locale // is identical with the same url with default locale. // For example, if `en` is default locale, then `/en/about` and `/about` From 0be4cd159e360604533de7eafb3f3327abbd8e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruan=20P=C3=A9pe?= Date: Wed, 22 Jul 2020 00:16:27 -0300 Subject: [PATCH 3/4] Fallback locale handler --- .../LaravelLocalization.php | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/Mcamara/LaravelLocalization/LaravelLocalization.php b/src/Mcamara/LaravelLocalization/LaravelLocalization.php index e4000b5..250e28f 100644 --- a/src/Mcamara/LaravelLocalization/LaravelLocalization.php +++ b/src/Mcamara/LaravelLocalization/LaravelLocalization.php @@ -78,6 +78,13 @@ class LaravelLocalization */ protected $defaultLocale; + /** + * Default fallback locale. + * + * @var string + */ + protected $defaultFallbackLocale; + /** * Supported Locales. * @@ -136,13 +143,19 @@ public function __construct() $this->request = $this->app['request']; $this->url = $this->app['url']; - // set default locale - $this->defaultLocale = $this->configRepository->get('app.locale'); $supportedLocales = $this->getSupportedLocales(); + // set default locale + $this->defaultLocale = $this->configRepository->get('app.locale'); if (empty($supportedLocales[$this->defaultLocale])) { throw new UnsupportedLocaleException('Laravel default locale is not in the supportedLocales array.'); } + + // set default fallback locale + $this->defaultFallbackLocale = $this->configRepository->get('app.fallback_locale'); + if (empty($supportedLocales[$this->defaultFallbackLocale])) { + throw new UnsupportedLocaleException('Laravel default fallback locale is not in the supportedLocales array.'); + } } /** @@ -190,6 +203,14 @@ public function setLocale($locale = null) } } + // Method available from laravel 7.21.0 + if (method_exists($this->app, 'setFallbackLocale')) { + $this->app->setFallbackLocale($this->getCurrentFallbackLocale()); + } else { + $this->configRepository->set('app.fallback_locale', $this->getCurrentFallbackLocale()); + $this->app['translator']->setFallback($this->getCurrentFallbackLocale()); + } + $this->app->setLocale($this->currentLocale); // Regional locale such as de_DE, so formatLocalized works in Carbon @@ -413,6 +434,16 @@ public function getDefaultLocale() return $this->defaultLocale; } + /** + * Returns default fallback locale. + * + * @return string + */ + public function getDefaultFallbackLocale() + { + return $this->defaultFallbackLocale; + } + /** * Return locales mapping. * @@ -581,6 +612,28 @@ public function getCurrentLocale() return $this->configRepository->get('app.locale'); } + /** + * Returns current fallback language. + * + * @return string current fallback language + */ + public function getCurrentFallbackLocale() + { + if ($this->configRepository->get('laravellocalization.handleFallbackLocale') == 'related'){ + if($this->checkLocaleInSupportedLocales(explode('_', $this->getCurrentLocaleRegional())[0])) + return explode('_', $this->getCurrentLocaleRegional())[0]; + } + + if (($this->configRepository->get('laravellocalization.handleFallbackLocale') == 'header') && !$this->app->runningInConsole()) { + $negotiator = new LanguageNegotiator($this->getDefaultFallbackLocale(), $this->getSupportedLocales(), $this->request); + + return $negotiator->negotiateLanguage([$this->getCurrentLocale()]); + } + + // or get application default fallback language + return $this->configRepository->get('app.fallback_locale'); + } + /** * Returns current regional. * From c4f16d194e13f0e9e2355d3420a78b5cddb964d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruan=20P=C3=A9pe?= Date: Wed, 22 Jul 2020 00:18:42 -0300 Subject: [PATCH 4/4] Ignoring given array of locales Ignoring given array of locales, firstly used to get the fallback locale. --- .../LaravelLocalization/LanguageNegotiator.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Mcamara/LaravelLocalization/LanguageNegotiator.php b/src/Mcamara/LaravelLocalization/LanguageNegotiator.php index 1601753..ea5febc 100644 --- a/src/Mcamara/LaravelLocalization/LanguageNegotiator.php +++ b/src/Mcamara/LaravelLocalization/LanguageNegotiator.php @@ -93,12 +93,15 @@ public function __construct($defaultLocale, $supportedLanguages, Request $reques * Quality factors in the Accept-Language: header are supported, e.g.: * Accept-Language: en-UK;q=0.7, en-US;q=0.6, no, dk;q=0.8 * + * @param array $ignoreLanguages + * * @return string The negotiated language result or app.locale. */ - public function negotiateLanguage() + public function negotiateLanguage( $ignoreLanguages = [] ) { $matches = $this->getMatchesFromAcceptedLanguages(); foreach ($matches as $key => $q) { + if( in_array($key, $ignoreLanguages) ) continue; $key = ($this->configRepository->get('laravellocalization.localesMapping')[$key]) ?? $key; @@ -113,6 +116,7 @@ public function negotiateLanguage() // Search for acceptable locale by 'regional' => 'af_ZA' or 'lang' => 'af-ZA' match. foreach ( $this->supportedLanguages as $key_supported => $locale ) { if ( (isset($locale['regional']) && $locale['regional'] == $key) || (isset($locale['lang']) && $locale['lang'] == $key) ) { + if( in_array($key_supported, $ignoreLanguages) ) continue 2; return $key_supported; } } @@ -120,6 +124,10 @@ public function negotiateLanguage() // If any (i.e. "*") is acceptable, return the first supported format if (isset($matches['*'])) { reset($this->supportedLanguages); + + while ( in_array( key($this->supportedLanguages), $ignoreLanguages) ) { + next($this->supportedLanguages); + } return key($this->supportedLanguages); } @@ -127,7 +135,7 @@ public function negotiateLanguage() if ($this->use_intl && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $http_accept_language = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']); - if (!empty($this->supportedLanguages[$http_accept_language])) { + if (!empty($this->supportedLanguages[$http_accept_language]) && !in_array( $http_accept_language, $ignoreLanguages)) { return $http_accept_language; } } @@ -136,7 +144,7 @@ public function negotiateLanguage() $remote_host = explode('.', $this->request->server('REMOTE_HOST')); $lang = strtolower(end($remote_host)); - if (!empty($this->supportedLanguages[$lang])) { + if (!empty($this->supportedLanguages[$lang]) && !in_array( $lang, $ignoreLanguages)) { return $lang; } }