tractorcow-farm / silverstripe-fluent

Multi-language translate module for Silverstripe, without having to manage separate site trees.
BSD 3-Clause "New" or "Revised" License
91 stars 109 forks source link

Support language preferences without region (e.g. "en", "fr" etc instead of "en-US", "fr-CA" etc) #675

Open JorisDebonnet opened 3 years ago

JorisDebonnet commented 3 years ago

I have a site with three languages: English, French and Dutch. The specific locales are en_us, fr_be and nl_be, but the _be doesn't really matter; it's meant for all visitors of those languages. I know Fluent has a focus on separate locales, but I only need it for the separate languages. I'm using version 5.0.0.

Now, when I test the language detection on this website, I notice that I always just get the global default, which is English. That's despite my setting in Chrome for "Dutch" and "French" as prefered languages. Note that "Dutch (Belgium)" and "French (Belgium)" do not even appear in Chrome's language settings.

The header that Chrome is sending looks like this: Accept-Language: fr,nl;q=0.9,en-BE;q=0.8,en-US;q=0.7,en;q=0.6

Due to the missing region part, Fluent's BrowserLocaleDetector currently does not find a match those two first prefered languages. In other words, BrowserLocaleDetector is ignoring "simplified" language preferences.

I would argue that if a "prefered locale" of only 2 characters is encountered, it should just match that with the first matching locale that is available in the site.

JorisDebonnet commented 3 years ago

A simplistic way to solve this - the way I have done it for now - is by configuring to use my own LocaleDetector (as explained here) and then replacing line 64:

if ($localeObj->isLocale($browserLocale)) {

with the following instead:

if ($localeObj->isLocale($browserLocale)
    || strlen($browserLocale) === 2 && explode('_', $localeObj->Locale)[0] === $browserLocale) {

I guess a 'better' fix might be if isLocale could match 2-character locales?