For some time, I've been using something like this to get my user's country (ISO-3166):
const region = navigator.language.split('-')[1]; // 'US'
I've always assumed the string would be similar to en-US
-- where the country would hold the 2nd position of the array.
I am thinking this assumption is incorrect. According to MDN docs, navigator.language
returns: "string representing the language version as defined in BCP 47." Reading BCP 47, the primary language subtag is guaranteed to be first (e.g., 'en') but the region code is not guaranteed to be the 2nd subtag. There can be subtags that preceed and follow the region subtag.
For example "sr-Latn-RS"
is a valid BCP 47 language tag:
sr | Latn | RS
primary language | script subtag | region subtag
Is the value returned from navigator.language
a subset of BCP 47 containing only language and region? Or is there a library or regex that is commonly used to extract the region subtag from a language tag?
To get the user's locale in the browser, access the first element of the languages property on the navigator object, e.g. navigator. languages[0] . The property returns an array of strings that represent the user's preferred languages.
The Navigator. language read-only property returns a string representing the preferred language of the user, usually the language of the browser UI.
A locale is a location-based language setting that determines which conversational settings and strings to display. The user specifies their locale using settings on their device. They may change this setting whenever they wish, including during a conversation with a Business Messages agent.
Your solution is based on the false premise that the browser's language tag reliably matches the user's country. E.g., I have set my browser language to German, even though I am living nowhere near Germany at the moment, but rather in the United States.
Also, for example in Chrome, many language packs do not require you to specify the region modifier. Setting Chrome's display language to German
provides the following language tag:
> navigator.language
< "de"
No region tag at all, and a fairly common language.
Bottom line is, my browser setup results in language tag de
, even though I live in the United States.
A more accurate and possibly reliable way to determine the user's location would be to derive it from the IP address associated with the request. There are numerous services that offer this service. ip-api.com is one of them:
$.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>
Regex found here: 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'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With