From d62a8ad49659c7002de10f328df77a4133215e4b Mon Sep 17 00:00:00 2001 From: Yannis Viol Date: Tue, 3 Sep 2024 08:23:02 +0200 Subject: [PATCH 1/3] [TASK] Task-0: add frontend language cookie functionality --- .../Middleware/LanguageRedirectMiddleware.php | 59 +++++++++++++++++-- Configuration/Settings.yaml | 2 + Readme.md | 4 ++ 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/Classes/Middleware/LanguageRedirectMiddleware.php b/Classes/Middleware/LanguageRedirectMiddleware.php index c9e27a1..0855807 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 ); } @@ -122,4 +134,39 @@ protected function findMatchingPresetByAcceptLanguageHeader(string $acceptLangua return null; } + + /** + * 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); + + 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 + ); + + if ($preset !== null) { + return $preset; + } + + return null; + } } diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index 4280286..e33fbb8 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: _fe_language diff --git a/Readme.md b/Readme.md index 20f05b5..821001a 100644 --- a/Readme.md +++ b/Readme.md @@ -15,6 +15,8 @@ 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. ```yaml Wegmeister: @@ -23,4 +25,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 name + feLanguageCookieName: _fe_language ``` From fa02aa73a76a9115a1f8dbf591ae1c60b27c85e4 Mon Sep 17 00:00:00 2001 From: Yannis Viol Date: Tue, 3 Sep 2024 08:25:23 +0200 Subject: [PATCH 2/3] [TASK] Task-0: --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 821001a..402ce94 100644 --- a/Readme.md +++ b/Readme.md @@ -25,6 +25,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 name + # configure the name of your frontend language cookie feLanguageCookieName: _fe_language ``` From d74252e52cb49cccdedb856ae3afa173342965dd Mon Sep 17 00:00:00 2001 From: Yannis Viol Date: Thu, 12 Sep 2024 10:22:17 +0200 Subject: [PATCH 3/3] [TASK] Task-0: update codebase to improve readability and expandability --- .../Middleware/LanguageRedirectMiddleware.php | 37 +++++++++---------- Configuration/Settings.yaml | 4 +- Readme.md | 7 +++- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/Classes/Middleware/LanguageRedirectMiddleware.php b/Classes/Middleware/LanguageRedirectMiddleware.php index 0855807..88f377c 100644 --- a/Classes/Middleware/LanguageRedirectMiddleware.php +++ b/Classes/Middleware/LanguageRedirectMiddleware.php @@ -105,31 +105,16 @@ 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]; - } - - $preset = $this->contentDimensionPresetSource->findPresetByUriSegment( - 'language', - $languageCode - ); - - if ($preset !== null) { - return $preset; - } - - // No preset for the detected locale found, continue with next part - array_shift($parts); - $acceptLanguageHeader = implode(',', $parts); + return $resolvedLocale; } return null; @@ -147,6 +132,20 @@ protected function findMatchingPresetByFeLanguageCookie(string $feLanguageCookie { $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; diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index e33fbb8..212c8d6 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -2,5 +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: _fe_language + # Configure the name of your frontend language cookie name + feLanguageCookieName: '' diff --git a/Readme.md b/Readme.md index 402ce94..fa33784 100644 --- a/Readme.md +++ b/Readme.md @@ -17,6 +17,9 @@ Then run `composer update` in your project root. 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: @@ -25,6 +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 + # configure the name of your frontend language cookie + feLanguageCookieName: _fe_language ```