use Intl.DisplayNames, add polyfill

This commit is contained in:
Samuel Newman
2025-12-06 17:45:22 +02:00
parent 60dac90dcc
commit 7a6aa60e7d
6 changed files with 179 additions and 327 deletions
@@ -7,6 +7,7 @@ import {
getDefaultCountry,
INTERNATIONAL_TELEPHONE_CODES,
} from '#/lib/international-telephone-codes'
import {regionName} from '#/locale/helpers'
import {isWeb} from '#/platform/detection'
import {atoms as a, web} from '#/alf'
import * as Select from '#/components/Select'
@@ -35,14 +36,18 @@ export function InternationalPhoneCodeSelect({
const items = useMemo(() => {
return (
Object.entries(INTERNATIONAL_TELEPHONE_CODES)
.map(([value, {name, code, unicodeFlag, svgFlag}]) => ({
value,
name: name(i18n),
code,
label: `${name(i18n)} ${code}`,
unicodeFlag,
svgFlag,
}))
.map(([value, {code, unicodeFlag, svgFlag}]) => {
const name = regionName(value, i18n.locale)
return {
value,
name,
code,
label: `${name} ${code}`,
unicodeFlag,
svgFlag,
}
})
// boost the default value to the top, then sort by name
.sort((a, b) => {
if (a.value === defaultCountry) return -1
@@ -50,7 +55,7 @@ export function InternationalPhoneCodeSelect({
return a.name.localeCompare(b.name)
})
)
}, [i18n, defaultCountry])
}, [i18n.locale, defaultCountry])
const selected = useMemo(() => {
return items.find(item => item.value === value)
File diff suppressed because it is too large Load Diff
+42 -1
View File
@@ -57,7 +57,7 @@ function getLocalizedLanguage(
export function languageName(language: Language, appLang: string): string {
// if Intl.DisplayNames is unavailable on the target, display the English name
if (!(Intl as any).DisplayNames) {
if (!Intl.DisplayNames) {
return language.name
}
@@ -279,3 +279,44 @@ export function findSupportedAppLanguage(languageTags: (string | undefined)[]) {
}
return AppLanguage.en
}
/**
* Gets region name for a given country code and language.
*
* Falls back to English if unavailable/error, and if that fails, returns the country code.
*
* Intl.DisplayNames is widely available + has been polyfilled on native
*/
export function regionName(countryCode: string, appLang: string): string {
const translatedName = getLocalizedRegionName(countryCode, appLang)
if (translatedName) {
return translatedName
}
// Fallback: get English name. Needed for i.e. Esperanto
const englishName = getLocalizedRegionName(countryCode, 'en')
if (englishName) {
return englishName
}
// Final fallback: return country code
return countryCode
}
function getLocalizedRegionName(
countryCode: string,
appLang: string,
): string | undefined {
try {
const allNames = new Intl.DisplayNames([appLang], {
type: 'region',
fallback: 'none',
})
return allNames.of(countryCode)
} catch (err) {
console.warn('Error getting localized region name:', err)
return undefined
}
}
+46
View File
@@ -3,8 +3,10 @@
import '@formatjs/intl-locale/polyfill-force'
import '@formatjs/intl-pluralrules/polyfill-force'
import '@formatjs/intl-numberformat/polyfill-force'
import '@formatjs/intl-displaynames/polyfill-force'
import '@formatjs/intl-pluralrules/locale-data/en'
import '@formatjs/intl-numberformat/locale-data/en'
import '@formatjs/intl-displaynames/locale-data/en'
import {useEffect} from 'react'
import {i18n} from '@lingui/core'
@@ -64,6 +66,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/an'),
import('@formatjs/intl-numberformat/locale-data/es'),
import('@formatjs/intl-displaynames/locale-data/es'),
])
break
}
@@ -72,6 +75,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/ast'),
import('@formatjs/intl-numberformat/locale-data/ast'),
import('@formatjs/intl-displaynames/locale-data/ast'),
])
break
}
@@ -80,6 +84,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/ca'),
import('@formatjs/intl-numberformat/locale-data/ca'),
import('@formatjs/intl-displaynames/locale-data/ca'),
])
break
}
@@ -88,6 +93,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/cy'),
import('@formatjs/intl-numberformat/locale-data/cy'),
import('@formatjs/intl-displaynames/locale-data/cy'),
])
break
}
@@ -96,6 +102,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/da'),
import('@formatjs/intl-numberformat/locale-data/da'),
import('@formatjs/intl-displaynames/locale-data/da'),
])
break
}
@@ -104,6 +111,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/de'),
import('@formatjs/intl-numberformat/locale-data/de'),
import('@formatjs/intl-displaynames/locale-data/de'),
])
break
}
@@ -112,6 +120,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/el'),
import('@formatjs/intl-numberformat/locale-data/el'),
import('@formatjs/intl-displaynames/locale-data/el'),
])
break
}
@@ -120,6 +129,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/en'),
import('@formatjs/intl-numberformat/locale-data/en-GB'),
import('@formatjs/intl-displaynames/locale-data/en-GB'),
])
break
}
@@ -128,6 +138,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/eo'),
import('@formatjs/intl-numberformat/locale-data/eo'),
import('@formatjs/intl-displaynames/locale-data/eo'),
])
break
}
@@ -136,6 +147,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/es'),
import('@formatjs/intl-numberformat/locale-data/es'),
import('@formatjs/intl-displaynames/locale-data/es'),
])
break
}
@@ -144,6 +156,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/eu'),
import('@formatjs/intl-numberformat/locale-data/eu'),
import('@formatjs/intl-displaynames/locale-data/eu'),
])
break
}
@@ -152,6 +165,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/fi'),
import('@formatjs/intl-numberformat/locale-data/fi'),
import('@formatjs/intl-displaynames/locale-data/fi'),
])
break
}
@@ -160,6 +174,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/fr'),
import('@formatjs/intl-numberformat/locale-data/fr'),
import('@formatjs/intl-displaynames/locale-data/fr'),
])
break
}
@@ -168,6 +183,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/fy'),
import('@formatjs/intl-numberformat/locale-data/fy'),
import('@formatjs/intl-displaynames/locale-data/fy'),
])
break
}
@@ -176,6 +192,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/ga'),
import('@formatjs/intl-numberformat/locale-data/ga'),
import('@formatjs/intl-displaynames/locale-data/ga'),
])
break
}
@@ -184,6 +201,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/gd'),
import('@formatjs/intl-numberformat/locale-data/gd'),
import('@formatjs/intl-displaynames/locale-data/gd'),
])
break
}
@@ -192,6 +210,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/gl'),
import('@formatjs/intl-numberformat/locale-data/gl'),
import('@formatjs/intl-displaynames/locale-data/gl'),
])
break
}
@@ -200,6 +219,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/hi'),
import('@formatjs/intl-numberformat/locale-data/hi'),
import('@formatjs/intl-displaynames/locale-data/hi'),
])
break
}
@@ -208,6 +228,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/hu'),
import('@formatjs/intl-numberformat/locale-data/hu'),
import('@formatjs/intl-displaynames/locale-data/hu'),
])
break
}
@@ -216,6 +237,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/ia'),
import('@formatjs/intl-numberformat/locale-data/ia'),
import('@formatjs/intl-displaynames/locale-data/ia'),
])
break
}
@@ -224,6 +246,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/id'),
import('@formatjs/intl-numberformat/locale-data/id'),
import('@formatjs/intl-displaynames/locale-data/id'),
])
break
}
@@ -232,6 +255,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/it'),
import('@formatjs/intl-numberformat/locale-data/it'),
import('@formatjs/intl-displaynames/locale-data/it'),
])
break
}
@@ -240,6 +264,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/ja'),
import('@formatjs/intl-numberformat/locale-data/ja'),
import('@formatjs/intl-displaynames/locale-data/ja'),
])
break
}
@@ -248,6 +273,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/km'),
import('@formatjs/intl-numberformat/locale-data/km'),
import('@formatjs/intl-displaynames/locale-data/km'),
])
break
}
@@ -256,11 +282,17 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/ko'),
import('@formatjs/intl-numberformat/locale-data/ko'),
import('@formatjs/intl-displaynames/locale-data/ko'),
])
break
}
case AppLanguage.ne: {
i18n.loadAndActivate({locale, messages: messagesNe})
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/ne'),
import('@formatjs/intl-numberformat/locale-data/ne'),
import('@formatjs/intl-displaynames/locale-data/ne'),
])
break
}
case AppLanguage.nl: {
@@ -268,6 +300,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/nl'),
import('@formatjs/intl-numberformat/locale-data/nl'),
import('@formatjs/intl-displaynames/locale-data/nl'),
])
break
}
@@ -276,6 +309,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/pl'),
import('@formatjs/intl-numberformat/locale-data/pl'),
import('@formatjs/intl-displaynames/locale-data/pl'),
])
break
}
@@ -284,6 +318,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/pt'),
import('@formatjs/intl-numberformat/locale-data/pt'),
import('@formatjs/intl-displaynames/locale-data/pt'),
])
break
}
@@ -292,6 +327,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/pt-PT'),
import('@formatjs/intl-numberformat/locale-data/pt-PT'),
import('@formatjs/intl-displaynames/locale-data/pt-PT'),
])
break
}
@@ -300,6 +336,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/ro'),
import('@formatjs/intl-numberformat/locale-data/ro'),
import('@formatjs/intl-displaynames/locale-data/ro'),
])
break
}
@@ -308,6 +345,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/ru'),
import('@formatjs/intl-numberformat/locale-data/ru'),
import('@formatjs/intl-displaynames/locale-data/ru'),
])
break
}
@@ -316,6 +354,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/sv'),
import('@formatjs/intl-numberformat/locale-data/sv'),
import('@formatjs/intl-displaynames/locale-data/sv'),
])
break
}
@@ -324,6 +363,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/th'),
import('@formatjs/intl-numberformat/locale-data/th'),
import('@formatjs/intl-displaynames/locale-data/th'),
])
break
}
@@ -332,6 +372,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/tr'),
import('@formatjs/intl-numberformat/locale-data/tr'),
import('@formatjs/intl-displaynames/locale-data/tr'),
])
break
}
@@ -340,6 +381,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/uk'),
import('@formatjs/intl-numberformat/locale-data/uk'),
import('@formatjs/intl-displaynames/locale-data/uk'),
])
break
}
@@ -348,6 +390,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/vi'),
import('@formatjs/intl-numberformat/locale-data/vi'),
import('@formatjs/intl-displaynames/locale-data/vi'),
])
break
}
@@ -356,6 +399,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/zh'),
import('@formatjs/intl-numberformat/locale-data/zh'),
import('@formatjs/intl-displaynames/locale-data/zh'),
])
break
}
@@ -364,6 +408,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/zh'),
import('@formatjs/intl-numberformat/locale-data/zh'),
import('@formatjs/intl-displaynames/locale-data/zh'),
])
break
}
@@ -372,6 +417,7 @@ export async function dynamicActivate(locale: AppLanguage) {
await Promise.all([
import('@formatjs/intl-pluralrules/locale-data/zh'),
import('@formatjs/intl-numberformat/locale-data/zh'),
import('@formatjs/intl-displaynames/locale-data/zh'),
])
break
}