527

I have been trying to detect the browser language preference using JavaScript.

If I set the browser language in IE in Tools>Internet Options>General>Languages, how do I read this value using JavaScript?

Same problem for Firefox. I'm not able to detect the setting for tools>options>content>languages using navigator.language.

Using navigator.userLanguage , it detects the setting done thru Start>ControlPanel>RegionalandLanguageOptions>Regional Options tab.

I have tested with navigator.browserLanguage and navigator.systemLanguage but neither returns the value for the first setting(Tools>InternetOptions>General>Languages)

I found a link which discusses this in detail, but the question remains unanswered :(

phihag
  • 278,196
  • 72
  • 453
  • 469
Annibigi
  • 5,895
  • 5
  • 23
  • 21
  • 10
    There is now (2020) an experimental feature supported by all browsers that returns an array of language preference: `navigator.languages //["en-US", "zh-CN", "ja-JP"]` – Cornelius Roemer Mar 09 '20 at 13:05

26 Answers26

339

I think the main problem here is that the browser settings don't actually affect the navigator.language property that is obtained via javascript.

What they do affect is the HTTP 'Accept-Language' header, but it appears this value is not available through javascript at all. (Probably why @anddoutoi states he can't find a reference for it that doesn't involve server side.)

I have coded a workaround: I've knocked up a google app engine script at http://ajaxhttpheaders.appspot.com that will return you the HTTP request headers via JSONP.

(Note: this is a hack only to be used if you do not have a back end available that can do this for you. In general you should not be making calls to third party hosted javascript files in your pages unless you have a very high level of trust in the host.)

I intend to leave it there in perpetuity so feel free to use it in your code.

Here's some example code (in jQuery) for how you might use it

$.ajax({ 
    url: "http://ajaxhttpheaders.appspot.com", 
    dataType: 'jsonp', 
    success: function(headers) {
        language = headers['Accept-Language'];
        nowDoSomethingWithIt(language);
    }
});

Hope someone finds this useful.

Edit: I have written a small jQuery plugin on github that wraps this functionality: https://github.com/dansingerman/jQuery-Browser-Language

Edit 2: As requested here is the code that is running on AppEngine (super trivial really):

class MainPage(webapp.RequestHandler):
    def get(self):
        headers = self.request.headers
        callback = self.request.get('callback')

        if callback:
          self.response.headers['Content-Type'] = 'application/javascript'
          self.response.out.write(callback + "(")
          self.response.out.write(headers)
          self.response.out.write(")")
        else:
          self.response.headers['Content-Type'] = 'text/plain'
          self.response.out.write("I need a callback=")

application = webapp.WSGIApplication(
                                     [('/', MainPage)],
                                     debug=False)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

Edit3: Have open sourced the app engine code here: https://github.com/dansingerman/app-engine-headers

DanSingerman
  • 36,066
  • 13
  • 81
  • 92
  • 3
    @msec I have posted the Python appengine script as requested. Note, if server side is available, this should be pretty simple in any language - this service really only needs to exist for those that don't have (or don't want to have) a server side component. – DanSingerman Apr 12 '11 at 09:36
  • 3
    hi dan, this question gots 14k views and still counting - maybe you want to release your script on github? regards, msec – mate64 Jul 08 '11 at 06:45
  • 1
    Are there other reliable sites that return HTTP request headers like Google? What I'm trying to do is redirecting user to their browswer language settings, and my site is global. So I need to rely on the site globally available and permenant. – Deckard Feb 14 '12 at 07:24
  • 1
    @deckard ummm - the Internet _is_ global. The appengine script should work fine anywhere on the Internet. However - this is really a hack for devs without a backend available - it should not be used in a 'real' site where you have control of a the back end. – DanSingerman Feb 14 '12 at 09:54
  • @DanSingerman, interesting script. However,you should use `application/javascript` for JSONP. Also, this is not technically valid JSONP, since you're using simple quotes, but that shouldn't matter for most purposes. – Matthew Flaschen May 20 '12 at 14:28
  • 1
    @MatthewFlaschen you're quite right (In my defence I wrote the script in about 5 minutes 2 years ago.) I'll fix it up when I have a chance. – DanSingerman May 20 '12 at 17:30
  • @DanSingerman, thanks. "simple quotes" should have been "single quotes". – Matthew Flaschen May 21 '12 at 00:38
  • Just wondering, what is the different between `navigator.language` and `Accept-Language`... – AGamePlayer Nov 07 '13 at 14:21
  • @AwQiruiGuo the former is usually the browser's UI language, while the latter is an ordered list of languages the user prefers to view content in. – Ronny Nov 23 '13 at 18:56
  • If the third party service should be more safe it should enable CORS ;) – Endless Jul 23 '14 at 20:46
  • Please note header['Accept-Language'] will get different result base on your browser. – Evan Lin Jul 06 '15 at 00:53
  • 1
    a much better cross-browser solution is now available, see @MarcoDemaio's answer, explained here http://gu.illau.me/posts/the-problem-of-user-language-lists-in-javascript/ – Mousey Aug 15 '15 at 01:36
  • I guess this might be out of date, because changing the language definitely did change the navigation.languages value. Also if you add a new language and move it to the top of the list, then you will get that value when you query on navigation.language. Also note that IE / Edge have been using the same engine as chrome for quite some time now, so it should be enough to use navigator.langauge (primary language) or navigator.languages (array of all languages) – RollingInTheDeep Feb 09 '22 at 10:32
  • Is there a non Jquery version of this? – Khom Nazid Apr 25 '22 at 12:17
321
var language = window.navigator.userLanguage || window.navigator.language;
alert(language); //works IE/SAFARI/CHROME/FF

window.navigator.userLanguage is IE only and it's the language set in Windows Control Panel - Regional Options and NOT browser language, but you could suppose that a user using a machine with Window Regional settings set to France is probably a French user.

navigator.language is FireFox and all other browser.

Some language code: 'it' = italy, 'en-US' = english US, etc.


As pointed out by rcoup and The WebMacheter in comments below, this workaround won't let you discriminate among English dialects when users are viewing website in browsers other than IE.

window.navigator.language (Chrome/FF/Safari) returns always browser language and not browser's preferred language, but: "it's pretty common for English speakers (gb, au, nz, etc) to have an en-us version of Firefox/Chrome/Safari." Hence window.navigator.language will still return en-US even if the user preferred language is en-GB.

Marco Demaio
  • 33,578
  • 33
  • 128
  • 159
  • Does `navigator.language` always return the same value for a particular language (e.g. `ja-jp` for Japanese)? Or, the value / format varies across browsers / OS? – moey Aug 02 '11 at 12:23
  • I'm not sure, but you can check for a substring of it, i.e. `if(language.indexOf('jp') !== -1) alert('this is japanese')` – Marco Demaio Aug 05 '11 at 16:02
  • 40
    This is not correct. Calling `navigator.language` in Chrome will return the language Chrome is displayed in, **NOT** the user's preferred language (which is the language at the top of the languages list). – thomaux Mar 15 '13 at 14:39
  • 18
    @Anzeo: low are chances of having you site visited by users that speak in one language, but install a browser in another language and later they also set another preferred language. As said by others there is no decent way, my answer is a simple short workaround for a task that usually does not end up into fatal errors. If you have to be absolutely sure of what language the user uses you could always ask him by adding on your site a select list and save its choice into a cookie. – Marco Demaio Mar 21 '13 at 17:13
  • @MarcoDemaio the OP asks a solution to detect the preference of the user. As Chrome is confusing in these settings, I added the note for future reference. We had the problem recently on our project and had to use the accepted answer. It's to determine the default, because our users can also set their preferred language on the platform. However this setting might be missing, hence the need of a default. – thomaux Mar 22 '13 at 09:13
  • 11
    @MarcoDemaio it's pretty common for English speakers (gb, au, nz, etc) to have an en-us version of Firefox/Chrome/Safari. Sometimes en-gb builds exist but they're not popular, and there's certainly none for other en variants. – rcoup Aug 22 '13 at 21:50
  • @rcoup: sorry, but i don't unsertsand youyr comment. Brits, Aussies, etc. they do all speak in English, and the 'Browser Language Preference' detected by my code will be exactly 'English'. – Marco Demaio Oct 05 '13 at 15:54
  • I think you might be confusing the browser's configured language with the browser's language preference. The first controls the menus, etc on the browser, the later affects the languages that the browser sends in the header to servers asking for those languages in response. So if the server denies your language and resorts to English you'd want to use English, not the browser's language. – user959690 Jan 16 '15 at 21:11
  • 8
    Chrome has `window.navigator.languages` with array of user preferred languages. – Styx Oct 06 '15 at 06:33
  • 1
    @Styx `window.navigator.languages` represents alphabetically sorted list of languages available in system for text input. For example: my system's UI and Chrome language is "ru". Also my native languages are "ru" (Russian) and "uk" (Ukrainian), so I have enabled keyboard layouts for these languages (as well as English layout) and Chrome for `window.navigator.languages` returns ["en-US", "en", "ru", "uk"]. Absolutely different order than my preference and language of my UI. – Oleksandr Oct 23 '15 at 13:24
  • Due to said above, navigator.languages can't be used for any kind of strict detection for user's language preference order. It can be used to obtain generic information about user, not his preferences. – Oleksandr Oct 23 '15 at 13:32
  • 2
    @stunpix - maybe Chrome auto add keybord layouts to preferred languages. But you can edit this list and `window.navigator.languages` has ordered list of languages from preferences: `chrome://settings/languages` – Styx Oct 25 '15 at 17:30
  • @Styx yep, seems Chrome do this at install time, since any changes in keyboard layout settings later do not change that Chrome setting. Anyway, average user do not change these language settings in browser, so no one should rely on them as on user's languages that are sorted by user preference. That's not true. – Oleksandr Oct 26 '15 at 11:09
  • Another observation with Chrome: for pages with foreign languages browser asks to translate these pages to one of languages defined in settings, but once you click in popped bar "never translate this language" – this language will be added to you language list. So when user is getting annoyed with this translation bar, he can press "never translate" button to just stop it popping. Is this preferred user language in such case? I think no. – Oleksandr Oct 26 '15 at 13:52
  • It is pretty common for aware non-native-english speakers to install browser in English language to be able to troubleshoot easier, and still prefer another language for non-technical stuff. – 9ilsdx 9rvj 0lo Sep 20 '18 at 08:20
  • @CodeGust: The link no longer works. Can you find a replacement? – Marcel Waldvogel May 12 '19 at 08:52
  • 1
    @MarcelWaldvogel http://web.archive.org/web/20170616234605/http://blog.ksol.fr/user-locale-detection-browser-javascript/ cached version – CodeGust May 13 '19 at 11:35
  • 3
    @thomaux, no longer true. Now `navigator.language` in Chrome returns the first element of the list `navigator.languages`. This change makes it now impossible to know for sure the language of the browser's UI. – GetFree Nov 26 '19 at 23:50
  • The Accept-Language HTTP header in every HTTP request from the user's browser uses the same value for the navigator.languages property except for the extra qvalues (quality values) field (e.g. en-US;q=0.8). from https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/languages – Miguel Jun 05 '20 at 12:30
  • https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages Clearly states that navigator.language is the first element in the navigator.languages array. – RollingInTheDeep Feb 09 '22 at 10:35
232

Update of year 2014.

Now there is a way to get Accept-Languages in Firefox and Chrome using navigator.languages (works in Chrome >= 32 and Firefox >= 32)

Also, navigator.language in Firefox these years reflects most preferred language of content, not language of UI. But since this notion is yet to be supported by other browsers, it is not very useful.

So, to get most preferred content language when possible, and use UI language as fallback:

navigator.languages
    ? navigator.languages[0]
    : (navigator.language || navigator.userLanguage)
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Tim Babych
  • 3,356
  • 1
  • 20
  • 13
  • 20
    An alternative implementation which gets the preferred list of languages, or falls back to the UI language (both as arrays) is: `window.navigator.languages || [window.navigator.language || window.navigator.userLanguage]` – Dave Nov 15 '14 at 13:12
  • 3
    Note that this does not work in our 'most-favorite' browser, IE (tested with IE 11). – Yaba Nov 17 '14 at 13:36
  • 3
    His answer works fine in IE (tested 8-11). This should be the accepted answer. – Justin Jun 29 '15 at 19:35
  • 9
    Getting language with `navigator.languages[0]` is bad idea. My system's default language is Russian and `navigator.language` returns correct lang code "ru". But `navigator.languages` returns `["en-US", "en", "ru", "uk"]`. So getting language with 0 index will give you "en-US" which is incorrect for my system. Please don't use navigator.languages to detect current system's language. – Oleksandr Oct 23 '15 at 12:49
  • 9
    And one more thing: `navigator.languages` represents alphabetically(!) sorted list of languages available for text input in user's system. They are not sorted in order of user's preference. – Oleksandr Oct 23 '15 at 13:11
  • 12
    @stunpix this is not about system's language, but about in-browser preference. Which might or might not coincide with system's language, depending on which browser was installed. I suggest you take a look at your browser's settings. Firefox: Preferences-Content-Languages, Chrome: Settings (advanced) - Languages – Tim Babych Oct 23 '15 at 15:37
  • 29
    @stunpix No, this is not correct. The order of prefered languages in the array reflects the order set by user: https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/languages – StanE Aug 19 '16 at 12:34
  • 3
    @StanE For some reason this was correct on moment of writing, because I had setup that always returned me sorted array, despite of my settings (I double checked that). Now it's no longer correct and I can't reproduce my previous statement, so it's no longer correct. – Oleksandr Sep 01 '16 at 11:19
  • BTW, navigator.language[s] have unstable behavior across browsers and you should consider this behavior: `navigator.language` is a browser's UI lang. Chrome automatically sets its UI lang to system's, but FF doesn't do that automatically, so FF's lang could be != system's lang (for example freshly installed Ubuntu has FF with only english UI and other langs must be installed manually). `navigator.languages` – user's order preference. Chrome changes this list by pushing current system's lang to top of list, but FF still has a static list which should be sorted manually. – Oleksandr Sep 01 '16 at 11:48
  • 2
    All good. I've just checked myself (hate to do that, as you have to restart the browser - at least chrome). 1. `navigator.languages` - array is in the order you arrange your languages in browser settings (chrome is less intuitive that you can order them, as there is no indicator that you can drag the items in the list; Firefox has move up/down buttons) 2. navigator.language - returns the current language (the one set as default) Of course, I've tried in Chrome and Firefox, not sure about IE and what `navigator.userLanguage` returns... but I'm not even opening "that" (ie IE) :))) – MrCroft Sep 13 '16 at 23:20
  • 1
    I have my OS language (i.e. Chrome's UI language) set to en_US, preferred browser languages set to de, en_US, en_GB, en in that order. `navigator.language` returns `"de"` for me, so it seems to be equivalent to `navigator.languages[0]`, at least in more recent versions of Chrome. – Patrick Oscity Apr 03 '18 at 11:39
  • 1
    Yes, can confirm it works now in Chrome 65 on Mac. Interestingly the bug about navigator.language is not closed yet https://bugs.chromium.org/p/chromium/issues/detail?id=101138 – Tim Babych Apr 05 '18 at 03:31
  • 1
    One liner is `const langs = [].concat(navigator.languages, navigator.language, navigator.userLanguage, navigator.browserLanguage, navigator.systemLanguage).filter(Boolean);` – Vitim.us Sep 24 '18 at 14:38
70

I came across this piece of code to detect browser's language in Angular Translate module, which you can find the source here. I slightly modified the code by replacing angular.isArray with Array.isArray to make it independent of Angular library.

var getFirstBrowserLanguage = function () {
    var nav = window.navigator,
    browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],
    i,
    language;

    // support for HTML 5.1 "navigator.languages"
    if (Array.isArray(nav.languages)) {
      for (i = 0; i < nav.languages.length; i++) {
        language = nav.languages[i];
        if (language && language.length) {
          return language;
        }
      }
    }

    // support for other well known properties in browsers
    for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
      language = nav[browserLanguagePropertyKeys[i]];
      if (language && language.length) {
        return language;
      }
    }

    return null;
  };

console.log(getFirstBrowserLanguage());
Hamid Tavakoli
  • 4,567
  • 1
  • 33
  • 34
56

let lang = window.navigator.languages ? window.navigator.languages[0] : null;
    lang = lang || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage;

let shortLang = lang;
if (shortLang.indexOf('-') !== -1)
    shortLang = shortLang.split('-')[0];

if (shortLang.indexOf('_') !== -1)
    shortLang = shortLang.split('_')[0];

console.log(lang, shortLang);

I only needed the primary component for my needs, but you can easily just use the full string. Works with latest Chrome, Firefox, Safari and IE10+.

Kristian Williams
  • 2,275
  • 22
  • 25
40

var language = navigator.languages && navigator.languages[0] || // Chrome / Firefox
               navigator.language ||   // All browsers
               navigator.userLanguage; // IE <= 10

console.log(language);

Try PWA Template https://github.com/StartPolymer/progressive-web-app-template

Josef Ježek
  • 2,208
  • 2
  • 17
  • 10
  • 9
    Just run your script, got `en-US`, on osX El Capitan in Spanish, Chrome set in Spanish, from Barcelona .. The list of allowed languages, and picking up the first of it `navigator.languages[0]`, is not the actual language the user is using. – elQueFaltaba Jul 07 '16 at 13:03
23

navigator.userLanguage for IE

window.navigator.language for firefox/opera/safari

rink.attendant.6
  • 44,500
  • 61
  • 101
  • 156
  • 6
    navigator.userLanguage wont give him what he wants. From userLanguage-docs: This property reflects the setting in the "Your locale (location)" box in the Regional Options of Control Panel for example, "English (United States). – anddoutoi Jun 25 '09 at 11:48
  • 2
    It actually says it will return "any of the possible return values listed in the Language Codes." such as "en" or "en-gb" http://msdn.microsoft.com/en-us/library/ie/ms533052.aspx http://msdn.microsoft.com/en-us/library/ie/ms534713.aspx – philfreo Sep 04 '13 at 18:13
22

I've been using Hamid's answer for a while, but it in cases where the languages array is like ["en", "en-GB", "en-US", "fr-FR", "fr", "en-ZA"] it will return "en", when "en-GB" would be a better match.

My update (below) will return the first long format code e.g. "en-GB", otherwise it will return the first short code e.g. "en", otherwise it will return null.

function getFirstBrowserLanguage() {
        var nav = window.navigator,
            browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],
            i,
            language,
            len,
            shortLanguage = null;

        // support for HTML 5.1 "navigator.languages"
        if (Array.isArray(nav.languages)) {
            for (i = 0; i < nav.languages.length; i++) {
                language = nav.languages[i];
                len = language.length;
                if (!shortLanguage && len) {
                    shortLanguage = language;
                }
                if (language && len>2) {
                    return language;
                }
            }
        }

        // support for other well known properties in browsers
        for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
            language = nav[browserLanguagePropertyKeys[i]];
            //skip this loop iteration if property is null/undefined.  IE11 fix.
            if (language == null) { continue; } 
            len = language.length;
            if (!shortLanguage && len) {
                shortLanguage = language;
            }
            if (language && len > 2) {
                return language;
            }
        }

        return shortLanguage;
    }

console.log(getFirstBrowserLanguage());

Update: IE11 was erroring when some properties were undefined. Added a check to skip those properties.

EamonnM
  • 2,201
  • 1
  • 13
  • 18
  • It works on every browser I've tested - desktop and mobile. Which browser are you having problems with? – EamonnM Jul 17 '18 at 17:24
  • 'browserLanguage', 'systemLanguage and, 'userLanguage' are not properties of chrome and firefox.. but 'language' is present in all browsers.. My bad that I didn't see that it would return first short code which answers the question.. Deleting my previous comment.. – Jry9972 Jul 18 '18 at 14:15
  • 2
    How common is it a problem people have preferences in the order ["en", "en-GB"] but want the preferences the other way around. I thought the languages were meant to be in the order of user preference. if it were ["fr", "en-GB"], wouldn't the preference be for French? – Brent Mar 09 '20 at 20:27
  • @Brent That's a good point. It would depend on what you need from it. For ["en", "en-GB"] I would want to get "en-GB" as it's a more specific version of the same language. ["fr", "en-GB"] is different as they are different languages, and "fr" could be a better result. – EamonnM Mar 10 '20 at 12:46
20

I've just come up with this. It combines newer JS destructuring syntax with a few standard operations to retrieve the language and locale.

var [lang, locale] = (
    (
        (
            navigator.userLanguage || navigator.language
        ).replace(
            '-', '_'
        )
    ).toLowerCase()
).split('_');

Hope it helps someone

MrMesees
  • 1,488
  • 19
  • 27
17

There is no decent way to get that setting, at least not something browser independent.

But the server has that info, because it is part of the HTTP request header (the Accept-Language field, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4)

So the only reliable way is to get an answer back from the server. You will need something that runs on the server (like .asp, .jsp, .php, CGI) and that "thing" can return that info. Good examples here: http://www.developershome.com/wap/detection/detection.asp?page=readHeader

Mihai Nita
  • 5,547
  • 27
  • 27
  • 3
    Keep in mind that this is not a particularly reliable way of serving the "correct" language to the user. Many users will want an alternate option - don't leave them stranded! – Paul McMillan Nov 10 '09 at 10:50
  • 6
    100% agree. Using that info it a best guess. You should allow the user to override it, if you get it wrong. And if there is a possibility that the user returns, you might remember that choice in a cookie. If the site requires authentication, you might have that info in a user profile. – Mihai Nita Nov 10 '09 at 11:12
9

I can't find a single reference that state that it's possible without involving the serverside.

MSDN on:

From browserLanguage:

In Microsoft Internet Explorer 4.0 and earlier, the browserLanguage property reflects the language of the installed browser's user interface. For example, if you install a Japanese version of Windows Internet Explorer on an English operating system, browserLanguage would be ja.

In Internet Explorer 5 and later, however, the browserLanguage property reflects the language of the operating system regardless of the installed language version of Internet Explorer. However, if Microsoft Windows 2000 MultiLanguage version is installed, the browserLanguage property indicates the language set in the operating system's current menus and dialogs, as found in the Regional Options of the Control Panel. For example, if you install a Japanese version of Internet Explorer 5 on an English (United Kingdom) operating system, browserLanguage would be en-gb. If you install Windows 2000 MultiLanguage version and set the language of the menus and dialogs to French, browserLanguage would be fr, even though you have a Japanese version of Internet Explorer.

Note This property does not indicate the language or languages set by the user in Language Preferences, located in the Internet Options dialog box.

Furthermore, it looks like browserLanguage is deprecated cause IE8 doesn't list it

thomaux
  • 19,133
  • 10
  • 76
  • 103
anddoutoi
  • 9,973
  • 4
  • 29
  • 28
  • +1, but where did you read that `navigator.browserLanguage` is deprecated? It's not written in the links to the MSDN articles in you answer, and I just tested it in IE11 and it works! I don't have IE8 anymore, but I tested it with the IE8 simulator and it works (I know the IE8 simulator is not the best option to test things). – Marco Demaio Aug 27 '14 at 16:31
  • Hmm, yeah that seems weird. But I have no clue how I came to that conclusion 5 years ago >. – anddoutoi Aug 28 '14 at 09:28
  • @anddoutoi It is not available in IE 8, because it was introduced in IE 9, so it's exactly the opposite of what you though. – Armin Šupuk Jun 17 '18 at 00:54
9

I had the same problem, and I wrote the following front-end only library that wraps up the code for multiple browsers. It's not much code, but nice to not have to copy and paste the same code across multiple websites.

Get it: acceptedlanguages.js

Use it:

<script src="acceptedlanguages.js"></script>
<script type="text/javascript">
  console.log('Accepted Languages:  ' + acceptedlanguages.accepted);
</script>

It always returns an array, ordered by users preference. In Safari & IE the array is always single length. In FF and Chrome it may be more than one language.

Leigh McCulloch
  • 1,886
  • 24
  • 23
8

I would like to share my code, because it works and it is different than the others given anwers. In this example, if you speak French (France, Belgium or other French language) you are redirected on the French page, otherwise on the English page, depending on the browser configuration:

<script type="text/javascript">
$(document).ready(function () {
    var userLang = navigator.language || navigator.userLanguage;
    if (userLang.startsWith("fr")) {
            window.location.href = '../fr/index.html';
    }
    else {
            window.location.href = '../en/index.html';
    }
});
</script>
bfontaine
  • 18,169
  • 13
  • 73
  • 107
Becca
  • 99
  • 1
  • 3
7

If you only need to support certain modern browsers then you can now use:

navigator.languages

which returns an array of the user's language preferences in the order specified by the user.

As of now (Sep 2014) this works on: Chrome (v37), Firefox (v32) and Opera (v24)

But not on: IE (v11)

Mr Incredible
  • 441
  • 4
  • 8
  • In case it helps anyone else, I had thought this would work in Safari in iOS 8 since I thought it fell in the _modern_ category. I was wrong. – Austin Thompson Oct 07 '14 at 16:55
7

Javascript way:

var language = window.navigator.userLanguage || window.navigator.language;//returns value like 'en-us'

If you are using jQuery.i18n plugin, you can use:

jQuery.i18n.browserLang();//returns value like '"en-US"'
JaskeyLam
  • 15,405
  • 21
  • 114
  • 149
7

If you are developing a Chrome App / Extension use the chrome.i18n API.

chrome.i18n.getAcceptLanguages(function(languages) {
  console.log(languages);
  // ["en-AU", "en", "en-US"]
});
warrickh
  • 1,616
  • 1
  • 16
  • 14
  • I like this. It's chrome specific, but doesn't electron use chromium under the hood? Does this work for just chrome, or any chromium project – MrMesees Mar 10 '19 at 22:11
  • This is only available from within a Chrome Extension. Its not available in Chrome on a regular web page. I'm not sure about Electron. – warrickh Mar 12 '19 at 06:10
6

For what it's worth, Wikimedia's Universal Language Selector library has hooks for doing this: https://www.mediawiki.org/wiki/Extension:UniversalLanguageSelector

See the function getFrequentLanguageList in resources/js/ext.uls.init.js . Direct link: https://gerrit.wikimedia.org/r/gitweb?p=mediawiki/extensions/UniversalLanguageSelector.git;a=blob;f=resources/js/ext.uls.init.js;hb=HEAD

It still depends on the server, or more specifically, the MediaWiki API. The reason I'm showing it is that it may provide a good example of getting all the useful information about the user's language: browser language, Accept-Language, geolocation (with getting country/language info from the CLDR), and of course, user's own site preferences.

Amir E. Aharoni
  • 1,308
  • 2
  • 13
  • 25
6

DanSingerman has a very good solution for this question.

The only reliable source for the language is in the HTTP-request header. So you need a server-side script to reply the request-header or at least the Accept-Language field back to you.

Here is a very simple Node.js server which should be compatible with DanSingermans jQuery plugin.

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end(JSON.stringify(req.headers));
}).listen(80,'0.0.0.0');
skython
  • 331
  • 4
  • 6
2

Dan Singerman's answer has an issue that the header fetched has to be used right away, due to the asynchronous nature of jQuery's ajax. However, with his google app server, I wrote the following, such that the header is set as part of the initial set up and can be used at later time.

<html>
<head>
<script>

    var bLocale='raw'; // can be used at any other place

    function processHeaders(headers){
        bLocale=headers['Accept-Language'];
        comma=bLocale.indexOf(',');
        if(comma>0) bLocale=bLocale.substring(0, comma);
    }

</script>

<script src="jquery-1.11.0.js"></script>

<script type="application/javascript" src="http://ajaxhttpheaders.appspot.com?callback=processHeaders"></script>

</head>
<body>

<h1 id="bLocale">Should be the browser locale here</h1>

</body>

<script>

    $("#bLocale").text(bLocale);

</script>
</html>
furins
  • 4,979
  • 1
  • 39
  • 57
1

If you don't want to rely on an external server and you have one of your own you can use a simple PHP script to achieve the same behavior as @DanSingerman answer.

languageDetector.php:

<?php
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
echo json_encode($lang);
?>

And just change this lines from the jQuery script:

url: "languageDetector.php",
dataType: 'json',
success: function(language) {
    nowDoSomethingWithIt(language);
}
Mijail
  • 186
  • 10
0

If you have control of a backend and are using django, a 4 line implementation of Dan's idea is:

def get_browser_lang(request):
if request.META.has_key('HTTP_ACCEPT_LANGUAGE'):
    return JsonResponse({'response': request.META['HTTP_ACCEPT_LANGUAGE']})
else:
    return JsonResponse({'response': settings.DEFAULT_LANG})

then in urls.py:

url(r'^browserlang/$', views.get_browser_lang, name='get_browser_lang'),

and on the front end:

$.get(lg('SERVER') + 'browserlang/', function(data){
    var lang_code = data.response.split(',')[0].split(';')[0].split('-')[0];
});

(you have to set DEFAULT_LANG in settings.py of course)

Gobi Dasu
  • 459
  • 1
  • 6
  • 22
0

Based on the answer here Accessing the web page's HTTP Headers in JavaScript I built the following script to get the browser language:

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
var contentLanguage = headers.match( /^content-language\:(.*)$/gm );
if(contentLanguage[0]) {
    return contentLanguage[0].split(":")[1].trim().toUpperCase();
}
Community
  • 1
  • 1
0

If you are using ASP .NET MVC and you want to get the Accepted-Languages header from JavaScript then here is a workaround example that does not involve any asynchronous requests.

In your .cshtml file, store the header securely in a div's data- attribute:

<div data-languages="@Json.Encode(HttpContext.Current.Request.UserLanguages)"></div>

Then your JavaScript code can access the info, e.g. using JQuery:

<script type="text/javascript">
$('[data-languages]').each(function () {
    var languages = $(this).data("languages");
    for (var i = 0; i < languages.length; i++) {
        var regex = /[-;]/;
        console.log(languages[i].split(regex)[0]);
    }
});
</script>

Of course you can use a similar approach with other server technologies as others have mentioned.

Johan Franzén
  • 2,355
  • 1
  • 17
  • 15
0

For who are looking for Java Server solution

Here is RestEasy

@GET
@Path("/preference-language")
@Consumes({"application/json", "application/xml"})
@Produces({"application/json", "application/xml"})
public Response getUserLanguagePreference(@Context HttpHeaders headers) {
    return Response.status(200)
            .entity(headers.getAcceptableLanguages().get(0))
            .build();
}
vanduc1102
  • 5,769
  • 1
  • 46
  • 43
0

i had a diffrent approach, this might help someone in the future:

the customer wanted a page where you can swap languages. i needed to format numbers by that setting (not the browser setting / not by any predefined setting)

so i set an initial setting depending on the config settings (i18n)

$clang = $this->Session->read('Config.language');
echo "<script type='text/javascript'>var clang = '$clang'</script>";

later in the script i used a function to determine what numberformating i need

function getLangsettings(){
  if(typeof clang === 'undefined') clang = navigator.language;
  //console.log(clang);
  switch(clang){
    case 'de':
    case 'de-de':
        return {precision : 2, thousand : ".", decimal : ","}
    case 'en':
    case 'en-gb':
    default:
        return {precision : 2, thousand : ",", decimal : "."}
  }
}

so i used the set language of the page and as a fallback i used the browser settings.

which should be helpfull for testing purposes aswell.

depending on your customers you might not need that settings.

0

I have a hack that I think uses very little code and is quite reliable.

Put your site's files in a subdirectory. SSL into your server and create symlinks to that subdirectory where your files are stored that indicate your languages.

Something like this:

ln -s /var/www/yourhtml /var/www/en
ln -s /var/www/yourhtml /var/www/sp
ln -s /var/www/yourhtml /var/www/it

Use your web server to read HTTP_ACCEPT_LANGUAGE and redirect to these "different subdirectories" according to the language value it provides.

Now you can use Javascript's window.location.href to get your url and use it in conditionals to reliably identify the preferred language.

url_string = window.location.href;
if (url_string = "http://yoursite.com/it/index.html") {
    document.getElementById("page-wrapper").className = "italian";
}
user612161
  • 77
  • 1
  • 4