关于本地化:用于检测浏览器语言偏好的JavaScript

JavaScript for detecting browser language preference

本问题已经有最佳答案,请猛点这里访问。

我一直在尝试使用JavaScript检测浏览器语言首选项。

如果我在Tools>Internet Options>General>Languages中的IE中设置浏览器语言,如何使用JavaScript读取此值?

Firefox的问题相同。 我无法使用navigator.language检测tools>options>content>languages的设置。

使用navigator.userLanguage,它会检测通过的设置
Start>ControlPanel>RegionalandLanguageOptions>Regional Options标签。

我已经使用navigator.browserLanguagenavigator.systemLanguage进行了测试,但都没有返回第一个设置的值(Tools>InternetOptions>General>Languages)

我找到了一个详细讨论这个问题的链接,但问题仍然没有答案:(


我认为这里的主要问题是浏览器设置实际上不会影响通过javascript获得的navigator.language属性。

它们影响的是HTTP"Accept-Language"标题,但看起来这个值根本无法通过javascript获得。 (可能为什么@anddoutoi声明他找不到不涉及服务器端的引用。)

我编写了一个解决方法:我在http://ajaxhttpheaders.appspot.com上敲了一个谷歌应用程序引擎脚本,它将通过JSONP返回HTTP请求标头。

(注意:如果您没有可以为您执行此操作的后端,则只能使用此hack。通常,您不应该在页面中调用第三方托管的javascript文件,除非您的页面非常高对主持人的信任程度。)

我打算永久保留它,所以请随意在你的代码中使用它。

这里有一些示例代码(在jQuery中),供您如何使用它

1
2
3
4
5
6
7
8
$.ajax({
    url:"http://ajaxhttpheaders.appspot.com",
    dataType: 'jsonp',
    success: function(headers) {
        language = headers['Accept-Language'];
        nowDoSomethingWithIt(language);
    }
});

希望有人觉得这很有用。

编辑:我在github上编写了一个小jQuery插件,它包含了这个功能:https://github.com/dansingerman/jQuery-Browser-Language

编辑2:这里要求的是在AppEngine上运行的代码(超级琐碎):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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()

编辑3:在这里开源应用程序引擎代码:https://github.com/dansingerman/app-engine-headers


1
2
var language = window.navigator.userLanguage || window.navigator.language;
alert(language); //works IE/SAFARI/CHROME/FF

window.navigator.userLanguage仅限IE,它是Windows控制面板中设置的语言 - 区域选项而非浏览器语言,但您可以假设使用设置为France的Window Regional设置的计算机的用户可能是法国用户。

navigator.language是FireFox和所有其他浏览器。

一些语言代码:'it' =意大利,'en-US' =英国美国等

正如rcoup和WebMacheter在下面的评论中所指出的,当用户在IE以外的浏览器中查看网站时,这种解决方法不会让您区分英语方言。

window.navigator.language(Chrome / FF / Safari)总是返回浏览器语言而不是浏览器的首选语言,但是:"英语使用者(gb,au,nz等)使用en-us版本的Firefox / Chrome /是非常常见的苹果浏览器。"因此,即使用户首选语言是en-GBwindow.navigator.language仍将返回en-US


2014年更新。

现在有一种方法可以使用navigator.languages在Firefox和Chrome中获取Accept-Languages(适用于Chrome> = 32和Firefox> = 32)

此外,Firefox中的navigator.language反映了最受欢迎的内容语言,而不是UI的语言。但由于这个概念尚未被其他浏览器支持,因此它不是很有用。

因此,要尽可能获得最首选的内容语言,并使用UI语言作为后备:

1
2
3
navigator.languages
    ? navigator.languages[0]
    : (navigator.language || navigator.userLanguage)


我在Angular Translate模块中遇到了这段代码来检测浏览器的语言,你可以在这里找到源代码。我通过将angular.isArray替换为Array.isArray来略微修改代码,使其独立于Angular库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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());


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

console.log(language);

  • https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/languages
  • https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language

试试PWA模板https://github.com/StartPolymer/progressive-web-app-template


1
2
3
4
5
6
7
8
<script type="text/javascript">
var lang = window.navigator.languages ? window.navigator.languages[0] : null;
    lang = lang || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage;
if (lang.indexOf('-') !== -1)
    lang = lang.split('-')[0];

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

我只需要主要组件来满足我的需求,但您可以轻松地使用完整的字符串。适用于最新的Chrome,Firefox,Safari和IE10 +。


没有合适的方法来获得该设置,至少不是浏览器独立的东西。

但服务器具有该信息,因为它是HTTP请求标头的一部分(Accept-Language字段,请参阅http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4)

因此,唯一可靠的方法是从服务器获得答案。您需要在服务器上运行的东西(如.asp,.jsp,.php,CGI),并且"thing"可以返回该信息。
这里有很好的例子:http://www.developershome.com/wap/detection/detection.asp?page = readHeader


IE的navigator.userLanguage

window.navigator.language for firefox / opera / safari


我一直在使用Hamid的答案,但是在语言数组就像["en","en-GB","en-US","fr-FR","fr","en -ZA"]当"en-GB"更好匹配时,它将返回"en"。

我的更新(下面)将返回第一个长格式代码,例如"en-GB",否则它将返回第一个短代码,例如"en",否则返回null。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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]];
            len = language.length;
            if (!shortLanguage && len) {
                shortLanguage = language;
            }
            if (language && len > 2) {
                return language;
            }
        }

        return shortLanguage;
    }

console.log(getFirstBrowserLanguage());


我遇到了同样的问题,我编写了以下前端库,它包含了多个浏览器的代码。代码不多,但不必在多个网站上复制和粘贴相同的代码。

得到它:acceptedlanguages.js

用它:

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

它总是返回一个数组,按用户首选项排序。在Safari&amp; IE数组总是单一长度。在FF和Chrome中,它可能不止一种语言。


如果您正在开发Chrome应用/扩展程序,请使用chrome.i18n API。

1
2
3
4
chrome.i18n.getAcceptLanguages(function(languages) {
  console.log(languages);
  // ["en-AU","en","en-US"]
});


我找不到一个引用,声明可以不涉及服务器端。

MSDN上:

  • navigator.browserLanguage
  • navigator.systemLanguage
  • navigator.userLanguage

来自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.

此外,看起来browserLanguage已被弃用,因为IE8没有列出它


我刚想出来了。它结合了较新的JS解构语法和一些标准操作来检索语言和语言环境。

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

希望它可以帮助某人


Javascript方式:

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

如果您使用的是jQuery.i18n插件,则可以使用:

1
jQuery.i18n.browserLang();//returns value like '"en-US"'


DanSingerman对这个问题有很好的解决方案。

该语言唯一可靠的来源是HTTP请求标头。
因此,您需要一个服务器端脚本来回复请求标头或至少回复Accept-Language字段。

这是一个非常简单的Node.js服务器,它应该与DanSingermans jQuery插件兼容。

1
2
3
4
5
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');


对于它的价值,维基媒体的通用语言选择器库有这样做的钩子:
https://www.mediawiki.org/wiki/Extension:UniversalLanguageSelector

请参阅resources / js / ext.uls.init.js中的函数getFrequentLanguageList。直接链接:
https://gerrit.wikimedia.org/r/gitweb?p=mediawiki/extensions/UniversalLanguageSelector.git;a=blob;f=resources/js/ext.uls.init.js;hb=HEAD

它仍然取决于服务器,或者更具体地说,取决于MediaWiki API。我展示它的原因是它可以提供一个很好的例子来获取有关用户语言的所有有用信息:浏览器语言,接受语言,地理定位(从CLDR获取国家/语言信息),当然,用户自己的网站首选项。


如果您只需要支持某些现代浏览器,那么您现在可以使用:

1
navigator.languages

它以用户指定的顺序返回用户语言首选项的数组。

截至目前(2014年9月),这适用于:
Chrome(第37版),
Firefox(v32)和
歌剧(第24集)

但不是:
IE(v11)


首先,请原谅我的英语。
我想分享我的代码,因为它有效,并且它与其他给出的答案不同。
在这个例子中,如果您说法语(法国,比利时或其他法语),您将被重定向到法语页面,否则在英语页面上,具体取决于浏览器配置:

1
2
3
4
5
6
7
8
9
10
<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';
                }
            });


由于jQuery的ajax的异步特性,Dan Singerman的答案有一个问题,即提取的标题必须立即使用。但是,通过他的谷歌应用服务器,我编写了以下内容,以便将标题设置为初始设置的一部分,并可在以后使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<html>
<head>


    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 src="jquery-1.11.0.js">

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

</head>
<body>

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

</body>



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


</html>


如果您控制后端并使用django,那么Dan的想法的4行实现是:

1
2
3
4
5
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})

然后在urls.py中:

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

在前端:

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

(你当然必须在settings.py中设置DEFAULT_LANG)


如果您不想依赖外部服务器并且拥有自己的服务器,则可以使用简单的PHP脚本来实现与@DanSingerman答案相同的行为。

languageDetector.php:

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

只需从jQuery脚本中更改以下行:

1
2
3
4
5
url:"languageDetector.php",
dataType: 'json',
success: function(language) {
    nowDoSomethingWithIt(language);
}

如果您正在使用ASP .NET MVC并且想要从JavaScript获取Accepted-Languages标头,那么这是一个不涉及任何异步请求的变通方法示例。

在.cshtml文件中,将标题安全地存储在div的data-属性中:

1
 

然后,您的JavaScript代码可以访问该信息,例如使用JQuery:

1
2
3
4
5
6
7
8
<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]);
    }
});

当然,您可以像其他人提到的那样使用与其他服务器技术类似的方法。


对于谁在寻找Java Server解决方案

这是RestEasy

1
2
3
4
5
6
7
8
9
@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();
}

我有一个不同的方法,这可能会有助于未来的人:

客户想要一个可以交换语言的页面。
我需要按照该设置格式化数字(不是浏览器设置/不是任何预定义的设置)

所以我根据配置设置设置初始设置(i18n)

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

稍后在脚本中我使用了一个函数来确定我需要什么数字格式

1
2
3
4
5
6
7
8
9
10
11
12
13
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 :"."}
  }
}

所以我使用了页面的设置语言,作为后备,我使用了浏览器设置。

这应该有助于测试目的。

根据您的客户,您可能不需要这些设置。


我有一个黑客,我认为使用非常少的代码,是非常可靠的。

将您网站的文件放在子目录中。 SSL进入您的服务器并创建符号链接到存储文件的子目录,该子目录指示您的语言。

像这样的东西:

1
2
3
ln -s /var/www/yourhtml /var/www/en
ln -s /var/www/yourhtml /var/www/sp
ln -s /var/www/yourhtml /var/www/it

使用您的Web服务器读取HTTP_ACCEPT_LANGUAGE并根据它提供的语言值重定向到这些"不同的子目录"。

现在,您可以使用Javascript的window.location.href来获取您的URL并在条件中使用它来可靠地识别首选语言。

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

基于这里的答案在JavaScript中访问网页的HTTP标头我构建了以下脚本来获取浏览器语言:

1
2
3
4
5
6
7
8
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();
}