使用navigator.language获取用户的区域

时间:2016-08-29 19:36:00

标签: javascript locale iso-3166 ietf-bcp-47

有一段时间,我一直在使用这样的东西来获取用户的国家/地区(ISO-3166):

const region = navigator.language.split('-')[1]; // 'US'

我总是假设字符串类似于en-US - 国家/地区将保持数组的第二位置

我认为这个假设不正确According to MDN docsnavigator.language返回:"表示BCP 47中定义的语言版本的字符串。" Reading BCP 47,主要语言子标签为保证是第一个(例如,' en')但区域代码不保证是第二个子标签。区域子标签之前和之后可以有子标签。

例如,"sr-Latn-RS"是有效的BCP 47语言标记:

sr                |  Latn           |  RS
primary language  |  script subtag  |  region subtag

navigator.language返回的值是否只包含语言和区域的BCP 47的子集?或者是否存在通常用于从语言标记中提取区域子标签的库或正则表达式?

7 个答案:

答案 0 :(得分:5)

您的解决方案基于错误的前提,即浏览器的语言标记可靠地匹配用户的国家/地区。例如,我已将我的浏览器语言设置为德语,尽管此刻我现在远在德国附近,而是在美国。

此外,例如在Chrome中,许多语言包不需要您指定区域修改器。将Chrome的显示语言设置为德语

enter image description here

提供以下语言标记:

> navigator.language
< "de"

根本没有区域标签,也是一种相当常见的语言。

一句话是,我的浏览器设置会生成语言标记de,即使我住在美国。

确定用户位置的更准确且可能可靠的方法是从与请求相关联的IP地址导出它。有许多服务提供此服务。 ip-api.com就是其中之一:

&#13;
&#13;
$.get("http://ip-api.com/json", function(response) {
  console.log(response.country);     // "United States"
  console.log(response.countryCode); // "US"
}, "jsonp");
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

在Firefox中,您可以在偏好设置中选择语言设置:

Geolocation API

语言列表包含269项,其中192项不包含任何地区代码。

该区域仅在语言根据位置具有不同变体时才有用。这样,用户可以告诉服务器他们更喜欢哪种语言变体。

请勿使用此方法来定位用户。这太不可靠了,因为用户可能没有指定任何区域,或者因为用户可能在另一个地方。

如果要查找用户,则应使用{{3}}。

答案 2 :(得分:1)

正则表达式在此处找到:https://github.com/gagle/node-bcp47/blob/master/lib/index.js

var re = /^(?:(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))$|^((?:[a-z]{2,3}(?:(?:-[a-z]{3}){1,3})?)|[a-z]{4}|[a-z]{5,8})(?:-([a-z]{4}))?(?:-([a-z]{2}|\d{3}))?((?:-(?:[\da-z]{5,8}|\d[\da-z]{3}))*)?((?:-[\da-wy-z](?:-[\da-z]{2,8})+)*)?(-x(?:-[\da-z]{1,8})+)?$|^(x(?:-[\da-z]{1,8})+)$/i;

let foo = re.exec('de-AT');      // German in Austria
let bar = re.exec('zh-Hans-CN'); // Simplified Chinese using Simplified script in mainland China

console.log(`region ${foo[5]}`); // 'region AT'
console.log(`region ${bar[5]}`); // 'region CN'

答案 3 :(得分:1)

请注意navigator.languagenavigator.languages

语言:

 console.log(navigator.language); // "fr"

langages:

 console.log(navigator.languages); // ["fr", "fr-FR", "en-US", "en"]

要查找国家/地区,请参阅Wikipedia on ISO 3166-1或使用javascript lib:

答案 4 :(得分:0)

正如@TimoSta所说,

试试这个

$.getJSON('http://freegeoip.net/json/', function(result) {
   alert(result.country_code);
});
来自Get visitors language & country code with javascript (client-side)

。见@noducks的答案

答案 5 :(得分:0)

您收到的值源自HTTP请求的Accept-Language标头。

标题的值可能非常复杂,如

Accept-Language: da, en-GB;q=0.8, en;q=0.7

顾名思义,Accept-Language标题基本上定义了可接受的语言,而不是国家。

语言标记还可能包含其他位置信息,例如&#39; en-GB&#39;但其他人喜欢&#39; en&#39;不要。

如果没有,则没有关于该国家的信息。

并不总是能够精确地映射像&#39; en&#39;之类的语言。到一个国家。 如果该语言是&#39; en&#39;,则该国家/地区可能是&#39; GB&#39;但也可能是美国&#39;

你可以做什么;

  • 如果语言包含一个语言,则仅确定国家/地区,例如&#39; en-GB&#39;
  • 如果语言不包含国家/地区,则您有以下选项:
  • 一些语言仅在一个国家/地区使用,例如丹麦语,丹麦语仅在丹麦使用(我在这里猜测),因此您可以映射这些案例。
  • 根据语言的不同,您可以对其他案例使用默认值,例如:地图&#39; en&#39;到&#39; GB&#39;
  • 您可以使用一般默认设置,例如&#39;美国&#39;对于所有情况,都无法确定国家。
  • 您可以使用其他信息,例如客户端IP地址以确定国家/地区
  • 最后,您可以要求用户输入国家/地区

我收集了一些有关Accept-Language标题here

的其他信息

答案 6 :(得分:0)

您现在可以使用国际化 API 中的 Locale 对象从区域设置标识符中提取区域。

const { region } = new Intl.Locale('sr-Latn-RS') // region => 'RS'

请注意,这当前与 Internet Explorer 不兼容。