Detect a user’s language preference with JavaScript

Last updated: April 4, 2022.

There are numerous situations in JavaScript where it is necessary to specify a language and country style for display values. For example, when formatting date and time using the Date object or currency formatting with the Internationalization API:

/* Date formatting */

new Date().toLocaleDateString('en-US'); // 4/1/2022
new Date().toLocaleDateString('en-GB'); // 01/04/2022
new Date().toLocaleDateString('de-DE'); // 1.4.2022


/* Currency formatting */
 
function formatCurrency (code, currency, amount) {
    return new Intl.NumberFormat(code, 
    {   
        style: 'currency',
        currency: currency 
    }).format(amount);
}
 
formatCurrency('en-US', 'USD', 39.99) // $39.99
formatCurrency('it-IT', 'JPY', 39.99) // 40 JPY
formatCurrency('en-IN', 'EUR', 39.99) // €39.99

In both examples, the accepted two-character language and country format is a concatenation of the ISO-639 language code and ISO-3166 country code. Mitch Fincher has very helpfully compiled a consolidated list on his homepage.

The country-language codes in the examples above have been hard-coded. But you can also generate these codes dynamically based upon a user’s language preference.

Detecting language preference

A user’s language preference can be detected by accessing the value of the language property on the globally available navigator object:

/* Return a user's preferred language */

window.navigator.language; // "en-US"
// or
navigator.language; // "en-US"

If a user has multiple language preferences, these can be detected by accessing languages. This returns an array of preferred languages, in order of preference:

/* Return a user's preferred languages */

window.navigator.languages; // ["en-US", "de-DE", "ja-JP"]
// or
navigator.languages; // ["en-US", "de-DE", "ja-JP"]

Both navigator.language and navigator.languages have widespread browser support. For the latest, see the browser compatibility tables for language and languages provided by CanIUse.

Implementation

In practice, it is a good idea to set a default value for a user's preferred language, just in case there is a problem with detection.

A 'longhand' solution for this is to create an if conditional statement, checking whether window.navigator.language was successful. If it is, its return value is the return value of the function. If not, a default value (e.g. "en-US") is returned:

/* Longhand language detection */

function detectLanguage(preferred) {
    preferred = window.navigator.language;
    if (!preferred) {
        const defaultLanguage = "en-US";
        return defaultLanguage;
    }
    return preferred;
}

const userLanguage = detectLanguage();
userLanguage // "en-US" or preferred if detected

The 'shorthand' solution is to set a default parameter using ES6 syntax:

/* Shorthand language detection */

function detectLanguage(preferred = "en-US") {
    preferred = window.navigator.language;
    return preferred;
}

const userLanguage = detectLanguage();
userLanguage // "en-US" or preferred if detected

Usage examples

#1: Today's date:

/* Formatting today's date */

function detectLanguage(preferred = "en-US") {
    preferred = window.navigator.language;
    return preferred;
}

const userLanguage = detectLanguage();
new Date().toLocaleDateString(userLanguage); // Formatted date

#2: Format currency:

/* Formatting numeric value as currency */

function detectLanguage(preferred = "en-US") {
    preferred = window.navigator.language;
    return preferred;
}

function formatCurrency (code, currency, amount) {
    return new Intl.NumberFormat(code, 
    {   
        style: 'currency',
        currency: currency 
    }).format(amount);
}

const userLanguage = detectLanguage();
formatCurrency(userLanguage, 'USD', 14.99) // 14.99 dollars formatted

Summary

Country code are used for a variety of purposes in JavaScript. One option is to hard-code these for a static outcome.

But you can also easily format display values to be consistent with a user's language preference using navigator.language.

This small but powerful functionality can make printed-values country-specific, improving the overall user experience of your website or app.

Related links