Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Browser language detection: inconsistency between user agent and window.navigator.language

I detect browser language like this:

 var language = window.navigator.userLanguage || window.navigator.language

Then I send this value to my webserver with AJAX call.
When I check the results I saw a weird thing. For example user agent of the browser says that current locale is tr-tr, but when I check for window.navigator.language I get the result as en.

All these browsers says that their language is en:

Mozilla/5.0 (Linux; U; Android 2.2.2; tr-tr; GM FOX Build/HuaweiU8350) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1, 
Mozilla/5.0 (Linux; U; Android 2.2.2; tr-tr; LG-P503 Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2
Mozilla/5.0 (Linux; U; Android 2.3.4; tr-tr; GT-S5670 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
Mozilla/5.0 (Linux; U; Android 2.3.6; tr-tr; GT-S5360 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 
Mozilla/5.0 (Linux; U; Android 2.3.6; tr-tr; GT-S5830i Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S7233E/S723EJVKB1; U; Bada/1.0; tr-tr) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.0 Mobile WQVGA SMM-MMS/1.2.0 OPN-B
Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S8500/S8500JVJE6; U; Bada/1.0; tr-tr) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.0 Mobile WVGA SMM-MMS/1.2.0 OPN-B
Mozilla/5.0 (X11; U; Linux x86_64; tr-tr) AppleWebKit/537.36 (KHTML, like Gecko)  Chrome/30.0.1599.114 Safari/537.36 Puffin/3.7.0.177AP
Mozilla/5.0 (Series40; NokiaC2-02/07.63; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/5.0.0.0.31
Mozilla/5.0 (Series40; Nokia311/07.36; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/2.3.0.0.54
Mozilla/5.0 (Series40; NokiaC3-00/08.70; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/2.3.0.0.49
Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; ASU2JS; rv:11.0) like Gecko

Should I consider anything more for browser language detection ?

My problem is detecting browser language. Regarding to user agents, current language is "tr", but window.navigator.language gives "en". Is it a known problem ? Shouldn't I trust window.navigator.language value ? Should I parse user agent for language ?

Edit:
I also checked Accept-language header for these requests. These values are consistent with request's user agent string.
So, window.navigator.language says "en", Accept-language header is "tr-TR, en-US", user agent string has "tr-tr" word.

like image 883
trante Avatar asked May 01 '14 19:05

trante


2 Answers

As far as browsers go, there are two relevant languages: the language of the browser's user interface and the language that the user prefers to view webpages in. These languages are often identical but they don't have to be. For example, a Norwegian user will often use a browser with an English-language user interface, yet prefer viewing web pages in Norwegian.

The user agent generally reflects the language of the browser's user interface. Typically, this language is fixed and can only be changed with significant effort - like reinstalling the browser (Chrome actually allows configuring browser language but even there you have to dig deep into browser preferences).

The preferred content languages on the other hand are easily configured in all browsers. The user can select any number of languages and their priority. That list will be sent in the Accept-Language header and allows the server to adjust the content accordingly (e.g. redirect the user to a language-specific page version by default).

So far it is very straightforward - you usually want to consider Accept-Language for your decisions rather than the user agent. The only complication is knowing which one the window.navigator.language property reflects. Originally, window.navigator.language was meant to give you the language of the browser's user interface (meaning that it would match the user agent). However, websites use it to make decisions about what language version to present to the user - so some browsers went over to generating its value based on the Accept-Language header (typically by taking the first entry in the list). That's definitely the case for Firefox 5 and higher, and Safari 7 uses the same logic (don't know when it was introduced there).

Side-notes:

  • As of Firefox 32 and Chrome 32 there is a new window.navigator.languages property which returns the full list of content preferences that the user chose.
  • Internet Explorer has a non-standard window.navigator.userLanguage property.
like image 119
Wladimir Palant Avatar answered Oct 27 '22 22:10

Wladimir Palant


Based on what you've said and your reluctance to use this answer, it looks like you should use the Accept-language header or else parse the userAgent string (though e.g. Firefox doesn't place the language into that string any more). Because you actually have access to the HTTP headers, I would recommend using them.

My suspicion regarding the inconsistencies you found is that browsers can be compiled with a locale and then run by a user who wants a different locale (consider somebody who just downloads the default en-US build or somebody who switches languages periodically).

You'll have to test various configurations and see what works for you. Consider testing with various different Firefox locale builds and Chrome configurations. You can also test by polling your users (use a cookie). Over time, perhaps you won't need the cookie because you'll get it "right" by default due to these tests, but there will always be an exception here or there, so it's still good to allow the end user to override your (smart) default.

like image 39
Adam Katz Avatar answered Oct 27 '22 21:10

Adam Katz