Quppa
Quppa

Reputation: 1913

Sorting-friendly language names with Intl.DisplayNames

Is there a way to use Intl.DisplayNames to get sorting-friendly language names where the base language comes first?

const languageNames = new Intl.DisplayNames(['en'], { type: 'language' });
console.log(languageNames.of('en'));
console.log(languageNames.of('en-AU'));
console.log(languageNames.of('fr'));
console.log(languageNames.of('fr-CA'));

The above snippet returns:

English
Australian English
French
Canadian French

I'm looking for values formatted as documented in the CLDR Language/Locale Name Patterns page:

English
English (Australia)
French
French (Canada)

Some languages have alt="menu" variants as of CLDR 36, e.g. Chinese, Cantonese for yue (instead of the default Cantonese), but I'm not sure if these are exposed via JavaScript (and aren't defined for the languages in my example above, anyway).

I found a related ticket in the CLDR Jira: ICU-21549: Fix the API to support language menus

Upvotes: 1

Views: 612

Answers (2)

Inkling
Inkling

Reputation: 3792

Setting the languageDisplay option to 'standard' produces the output you want:

const languageNames = new Intl.DisplayNames(['en'], {
  type: 'language',
  languageDisplay: 'standard'
});
console.log(languageNames.of('en'));
console.log(languageNames.of('en-AU'));
console.log(languageNames.of('fr'));
console.log(languageNames.of('fr-CA'));

I don't know if it's possible to access the menu variants through this API.

Upvotes: 1

Dhaval Geek Web
Dhaval Geek Web

Reputation: 11

We can achieve this with the help of Intl.DisplayNames translations { type: "region" }

code

const languageNames = new Intl.DisplayNames(['en'], { type: 'language' });
const regionNames = new Intl.DisplayNames(["en"], { type: "region" });
const languagesObj = {};
const languages = [];

languagesObj['en'] = languageNames.of('en');
languagesObj['en-AU'] = languageNames.of('en-AU');
languagesObj['fr'] = languageNames.of('fr');
languagesObj['fr-CA'] = languageNames.of('fr-CA');

for (let lang in languagesObj) {
    if (lang.includes('-')) {
        const indexOfCountryLang = lang.indexOf('-');

        try {
            const language = languageNames.of(lang.slice(0, indexOfCountryLang)) ? languageNames.of(lang.slice(0, indexOfCountryLang)) : '';
            const region = regionNames.of(lang.slice(indexOfCountryLang + 1)) ? regionNames.of(lang.slice(indexOfCountryLang + 1)) : '';

            lang = `${language} (${region})`;
        } catch (error) {
            lang = languagesObj[lang];
        }
    } else {
        lang = languagesObj[lang];
    }

    languages.push(lang);
}

console.log(languages);

output [ 'English', 'English (Australia)', 'French', 'French (Canada)' ]

if any of instance not available in the languageNames.of() or regionNames.of() then it will keep default string

Upvotes: 1

Related Questions