-
-
Notifications
You must be signed in to change notification settings - Fork 186
Closed
✨ Enhancement
Copy link
Milestone
Description
Description
I have a multi-language site:
- German (code:
de/ locale:de_DE) - British English (code:
en/ locale:en_GB) - American English (code:
en-us/ locale:en_US)
languages.detect option is set to true
Expected behavior
US Americans (en_US) should be redirected to example.com/en-us.
But they are redirected to example.com/en because $kirby->detectedLanguage() just looks after the language (de or en) part of the visitor’s locale and ignores the territory (US or GB) part of the
Screenshots
To reproduce
- Set browser language to
en_US - Visit example.com
- You are redirected to example.com/en, but should be redirected to example.com/en-us
Your setup
Kirby Version
4.7.0 (also tested with 5.0.0-beta.6)
Console output
Your system (please complete the following information)
- Device: MacBook
- OS: macOS 15
- Browser: Firefox
- Version: 138
Additional context
Suggested Solution
Update $kirby->detectedLanguage().
/**
* Detect the preferred language from the visitor object
*/
public function detectedLanguage(): Language|null
{
$languages = $this->languages();
$visitor = $this->visitor();
foreach ($visitor->acceptedLanguages() as $acceptedLang) {
// Find locale matches (e.g. en_GB => en_GB)
$matchLocale = function ($language) use ($acceptedLang) {
$languageLocale = $language->locale(LC_ALL);
$acceptedLocale = $acceptedLang->locale();
return Str::substr($languageLocale, 0, 5) === Str::substr($acceptedLocale, 0, 5);
};
// Find language matches (e.g. en_GB => en)
$matchLanguage = function ($language) use ($acceptedLang) {
$languageLocale = $language->locale(LC_ALL);
$acceptedLocale = $acceptedLang->locale();
return
$languageLocale === $acceptedLocale ||
$acceptedLocale === Str::substr($languageLocale, 0, 2);
};
if ($language = $languages->filter($matchLocale)?->first()) {
return $language;
}
if ($language = $languages->filter($matchLanguage)?->first()) {
return $language;
}
}
foreach ($visitor->acceptedLanguages() as $acceptedLang) {
if ($language = $languages->findBy('code', $acceptedLang->code())) {
return $language;
}
}
return $this->defaultLanguage();
}Metadata
Metadata
Assignees
Labels
No labels