20

一段时间以来,我一直在使用类似的方法来获取用户所在的国家/地区(ISO-3166):

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

我一直认为该字符串类似于en-US-- 国家将在数组的第二个位置

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

例如"sr-Latn-RS"是一个有效的 BCP 47 语言标签:

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

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

4

7 回答 7

9

您的解决方案基于浏览器的语言标签与用户所在国家/地区可靠匹配的错误前提。例如,我已将浏览器语言设置为德语,尽管我目前住在离德国不远的地方,而是住在美国。

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

在此处输入图像描述

提供以下语言标签:

> navigator.language
< "de"

根本没有地区标签,而且是一种相当通用的语言。

底线是,de即使我住在美国,我的浏览器设置也会导致 language tag 。


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

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

于 2016-09-01T19:36:24.540 回答
2

您现在可以使用Internationalization API 中的Locale对象从语言环境标识符中提取区域。

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

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

于 2021-08-08T23:26:31.373 回答
2

正则表达式在这里找到: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'
于 2016-09-02T01:52:27.923 回答
1

在 Firefox 中,您可以在首选项中选择您的语言设置:

在此处输入图像描述

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

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

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

如果你想定位用户,你应该使用Geolocation API

于 2016-09-01T21:15:35.243 回答
1

小心你有navigator.languagenavigator.languages

语言:

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

语言:

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

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

于 2016-09-08T17:24:13.303 回答
0

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

标头的值可能非常复杂,例如

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

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

语言标签也可能包含额外的位置信息,如“en-GB”,但其他如“en”则不包含。

如果不是,则没有有关该国家/地区的信息。

也不总是可以将像“en”这样的语言准确地映射到一个国家。如果语言是“en”,则国家可能是“GB”,但也可能是“US”。

你可以做什么 ;

  • 仅确定国家,如果语言包含一个,如 'en-GB'
  • 如果语言不包含国家/地区,您有以下选项:
  • 一些语言仅在一个国家/地区使用,例如“da”,丹麦语,仅在丹麦使用(我猜这里),因此您可以映射这些情况。
  • 您可以在其他情况下使用默认值,具体取决于语言,例如将“en”映射到“GB”
  • 对于无法确定国家/地区的所有情况,您可以使用一般默认值,例如“美国”。
  • 您可以使用其他信息,例如客户端 IP 地址来确定国家/地区
  • 最后你可以要求用户输入国家

我在此处收集了有关 Accept-Language 标头的一些附加信息

于 2016-09-08T18:01:45.047 回答
0

正如@TimoSta 所说,

尝试这个

$.getJSON('http://freegeoip.net/json/', function(result) {
   alert(result.country_code);
});

使用 javascript (client-side) 获取访问者语言和国家代码。查看@noducks 的回答

于 2016-09-08T07:02:31.037 回答