diff --git a/Classes/Middleware/LanguageRedirectMiddleware.php b/Classes/Middleware/LanguageRedirectMiddleware.php index c9e27a1..88f377c 100644 --- a/Classes/Middleware/LanguageRedirectMiddleware.php +++ b/Classes/Middleware/LanguageRedirectMiddleware.php @@ -24,6 +24,9 @@ class LanguageRedirectMiddleware implements MiddlewareInterface #[Flow\InjectConfiguration(path: 'languageCodeOverrides')] protected array $languageCodeOverrides; + #[Flow\InjectConfiguration(path: 'feLanguageCookieName')] + protected string $feLanguageCookieName; + /** * Redirect all requests to the homepage without a language prefix to the * homepage with the language that matches the browser language best. @@ -52,9 +55,18 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $defaultPreset = $this->contentDimensionPresetSource->getDefaultPreset('language'); - $preset = $this->findMatchingPresetByAcceptLanguageHeader( - $request->getHeader('Accept-Language')[0] ?? '', - ); + $preset = null; + + if ($this->feLanguageCookieName && isset($request->getCookieParams()[$this->feLanguageCookieName])) { + $feLanguageCookie = $request->getCookieParams()[$this->feLanguageCookieName]; + $preset = $this->findMatchingPresetByFeLanguageCookie($feLanguageCookie); + } + + if ($preset == null) { + $preset = $this->findMatchingPresetByAcceptLanguageHeader( + $request->getHeader('Accept-Language')[0] ?? '', + ); + } if ($preset == null) { $preset = $defaultPreset; @@ -63,9 +75,9 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface if ($preset === null) { throw new Exception( 'Unable to find a language preset for the detected locale ' - . 'and no default preset is configured. ' - . 'Check your content dimensions settings: ' - . 'Neos.ContentRepository.contentDimensions.language.', + . 'and no default preset is configured. ' + . 'Check your content dimensions settings: ' + . 'Neos.ContentRepository.contentDimensions.language.', 1701173151780 ); } @@ -93,31 +105,65 @@ protected function findMatchingPresetByAcceptLanguageHeader(string $acceptLangua $acceptLanguageHeader ); - if (!$detectedLocale instanceof Locale) { + $resolvedLocale = $this->resolveLocale($detectedLocale); + + if ($resolvedLocale === null) { // No Locale found, continue with next part array_shift($parts); $acceptLanguageHeader = implode(',', $parts); continue; } - $languageCode = $detectedLocale->getLanguage(); - if (isset($this->languageCodeOverrides[$languageCode])) { - // If there is a language code override, use it - $languageCode = $this->languageCodeOverrides[$languageCode]; - } + return $resolvedLocale; + } - $preset = $this->contentDimensionPresetSource->findPresetByUriSegment( - 'language', - $languageCode - ); + return null; + } - if ($preset !== null) { - return $preset; - } + /** + * Match frontend language cookie against given language dimensions. + * Return the Locale, that fits best. + * + * @param string $acceptLanguageHeader + * + * @return array|null + */ + protected function findMatchingPresetByFeLanguageCookie(string $feLanguageCookie): ?array + { + $detectedLocale = $this->localeDetector->detectLocaleFromLocaleTag($feLanguageCookie); + + return $this->resolveLocale($detectedLocale); + } + + /** + * Resolve a locale string and return it + * + * @param string $acceptLanguageHeader + * + * @return array|null + */ + protected function resolveLocale(string $localeString): ?array + { + $detectedLocale = $this->localeDetector->detectLocaleFromLocaleTag($localeString); + + if (!$detectedLocale instanceof Locale) { + // No Locale found + return null; + } + + $languageCode = $detectedLocale->getLanguage(); + if (isset($this->languageCodeOverrides[$languageCode])) { + // If there is a language code override, use it + $languageCode = $this->languageCodeOverrides[$languageCode]; + } + + $preset = $this->contentDimensionPresetSource->findPresetByUriSegment( + 'language', + $languageCode + ); - // No preset for the detected locale found, continue with next part - array_shift($parts); - $acceptLanguageHeader = implode(',', $parts); + if ($preset !== null) { + return $preset; } return null; diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index 4280286..212c8d6 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -2,3 +2,5 @@ Wegmeister: LanguageRedirect: # Add mappings for language codes if you use some different codes than the default ones. languageCodeOverrides: {} + # Configure the name of your frontend language cookie name + feLanguageCookieName: '' diff --git a/Readme.md b/Readme.md index 20f05b5..fa33784 100644 --- a/Readme.md +++ b/Readme.md @@ -15,6 +15,11 @@ Then run `composer update` in your project root. ## Configuration Sometimes language codes are not configured the same as in Neos. Therefore you can configure a mapping in your `Settings.yaml`: +Also you can configure a feLanguageCookieName to get a cookie value from your frontend in case you want your users last +opened language to reopen the next time he visits your website. +The `feLanguageCookieName` allows you to read a cookie that contains a default language. +Perhaps you can use this to always load the last language the user opened +by setting the cookie when he changes the language via the language menu on your website. ```yaml Wegmeister: @@ -23,4 +28,6 @@ Wegmeister: languageCodeOverrides: # For example, if you use "cz" instead of "cs" for Czech, you can add this mapping: cs: cz + # configure the name of your frontend language cookie + feLanguageCookieName: _fe_language ```