Подтвердить что ты не робот

Получение региона пользователя с помощью navigator.language

В течение некоторого времени я использовал что-то вроде этого, чтобы получить свою пользовательскую страну (ISO-3166):

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

Я всегда предполагаемый строка будет похожа на en-US - где страна будет удерживать вторую позицию массива.

Я думаю, что это предположение неверно. Согласно документам MDN, строка navigator.language возвращает: ", представляющую версию языка, как определено в BCP 47." Чтение BCP 47, первый языковой subtag гарантированно будет первым (например, 'en'), но региональный код не гарантированно будет 2-й подтекст. Могут быть субтаги, которые предшествуют и следуют за областью.

Например, "sr-Latn-RS" является допустимым тегом языка BCP 47:

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

Является ли значение, возвращаемое из navigator.language подмножеством BCP 47, содержащим только язык и регион? Или существует библиотека или регулярное выражение, которое обычно используется для извлечения субтегопа области из языкового тега?

4b9b3361

Ответ 1

Regex найдено здесь: 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'

Ответ 2

Ваше решение основано на ложной предпосылке, что тег языка браузера надежно соответствует стране пользователя. Например, я установил язык своего браузера на немецкий язык, хотя я сейчас живу поблизости от Германии, а скорее в Соединенных Штатах.

Кроме того, например, в Chrome многие языковые пакеты не требуют указания модификатора области. Настройка языка отображения Chrome на немецкий

введите описание изображения здесь

предоставляет следующий языковой тег:

> navigator.language
< "de"

Отсутствует тег области и довольно общий язык.

В нижней строке приведена настройка моего браузера с тегом языка de, хотя я живу в Соединенных Штатах.


Более точным и, возможно, надежным способом определения местоположения пользователя будет вывод его из 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>

Ответ 4

В Firefox вы можете выбрать свои языковые настройки в настройках:

введите описание изображения здесь

Список языков содержит 269 элементов, 192 из которых не содержат никакого регионального кода.

Область применима только тогда, когда язык имеет разные варианты в зависимости от местоположения. Таким образом, пользователи могут сообщать серверу, на каком языковом варианте они предпочитают ответ.

Не используйте этот подход для поиска пользователя. Это слишком ненадежно, потому что пользователь может не указывать какой-либо регион или потому, что пользователь может физически находиться в другом месте.

Если вы хотите найти пользователя, вы должны использовать API геолокации.

Ответ 6

Значение, которое вы получаете, связано с заголовком Accept-Language HTTP-запроса.

Значения заголовка могут быть довольно сложными, как

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

Как следует из названия, заголовок Accept-Language в основном определяет приемлемые языки, а не страны.

Языковой тег может содержать также дополнительную информацию о местоположении, как в "en-GB", но другие, такие как en, не делают.

В случае нет, информации о стране просто нет.

Также не всегда возможно точно отобразить язык, например, "en" в стране. Если язык "en", страна может быть "GB", но также может быть "США".

Что вы можете сделать,

  • Определите только страну, если язык содержит один, как в 'en-GB'
  • Если язык не содержит страну, у вас есть следующие параметры:
  • Несколько языков используются только в одной стране, например "да", датской, о которой говорят только в Дании (я угадываю здесь), поэтому вы можете сопоставить эти случаи.
  • Вы можете использовать значение по умолчанию для других случаев, в зависимости от языка, например. map 'en' to 'GB'
  • Вы можете использовать общий дефолт, такой как "США" для всех случаев, когда ни одна страна не может быть определена.
  • Вы можете использовать дополнительную информацию, например. IP-адрес клиентов для определения страны
  • Наконец, вы можете попросить пользователя войти в страну.

Я собрал дополнительную информацию о заголовке Accept-Language здесь