JavaScript for detecting browser language preference

JavascriptLocalizationInternationalization

Javascript Problem Overview


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 http://www.velocityreviews.com/forums/t99655-save-way-to-detect-browser-language.html">link</a> which discusses this in detail, but the question remains unanswered :(

Javascript Solutions


Solution 1 - Javascript

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

Solution 2 - Javascript

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.

Solution 3 - Javascript

Update of year 2014.

Now there is a way to get Accept-Languages in Firefox and Chrome using https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage.languages">navigator.languages</a>; (works in Chrome >= 32 and Firefox >= 32)

Also, https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage.language">navigator.language</a> 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)

Solution 4 - Javascript

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());

Solution 5 - Javascript

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+.

Solution 6 - Javascript

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

Solution 7 - Javascript

navigator.userLanguage for IE

window.navigator.language for firefox/opera/safari

Solution 8 - Javascript

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.

Solution 9 - Javascript

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

Solution 10 - Javascript

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

Solution 11 - Javascript

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.

Solution 12 - Javascript

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

Solution 13 - Javascript

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)

Solution 14 - Javascript

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"'

Solution 15 - Javascript

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"]
});

Solution 16 - Javascript

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');

Solution 17 - Javascript

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.

Solution 18 - Javascript

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>

Solution 19 - Javascript

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>

Solution 20 - Javascript

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);
}

Solution 21 - Javascript

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)

Solution 22 - Javascript

Based on the answer here https://stackoverflow.com/questions/220231/accessing-the-web-pages-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();
}

Solution 23 - Javascript

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.

Solution 24 - Javascript

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();
}

Solution 25 - Javascript

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.

Solution 26 - Javascript

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";
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnnibigiView Question on Stackoverflow
Solution 1 - JavascriptDanSingermanView Answer on Stackoverflow
Solution 2 - JavascriptMarco DemaioView Answer on Stackoverflow
Solution 3 - JavascriptTim BabychView Answer on Stackoverflow
Solution 4 - JavascriptHamid TavakoliView Answer on Stackoverflow
Solution 5 - JavascriptKristian WilliamsView Answer on Stackoverflow
Solution 6 - JavascriptJosef JežekView Answer on Stackoverflow
Solution 7 - JavascriptmitchbrysonView Answer on Stackoverflow
Solution 8 - JavascriptEamonnMView Answer on Stackoverflow
Solution 9 - JavascriptMihai NitaView Answer on Stackoverflow
Solution 10 - JavascriptMrMeseesView Answer on Stackoverflow
Solution 11 - JavascriptLeigh McCullochView Answer on Stackoverflow
Solution 12 - JavascriptanddoutoiView Answer on Stackoverflow
Solution 13 - JavascriptMr IncredibleView Answer on Stackoverflow
Solution 14 - JavascriptJaskeyLamView Answer on Stackoverflow
Solution 15 - JavascriptwarrickhView Answer on Stackoverflow
Solution 16 - JavascriptskythonView Answer on Stackoverflow
Solution 17 - JavascriptAmir E. AharoniView Answer on Stackoverflow
Solution 18 - JavascriptBeccaView Answer on Stackoverflow
Solution 19 - Javascriptuser3097579View Answer on Stackoverflow
Solution 20 - JavascriptMijailView Answer on Stackoverflow
Solution 21 - JavascriptGobi DasuView Answer on Stackoverflow
Solution 22 - JavascriptAndreas JantschnigView Answer on Stackoverflow
Solution 23 - JavascriptJohan FranzénView Answer on Stackoverflow
Solution 24 - Javascriptvanduc1102View Answer on Stackoverflow
Solution 25 - JavascriptArthur KielbasaView Answer on Stackoverflow
Solution 26 - Javascriptuser612161View Answer on Stackoverflow