Telephone country code select (#9473)

* add telephone code select

* add flags

* run svgo on flags

* get it somewhat working on web

* get web closed state working

* verify country code we get from geo

* trim down names to shorter common versions

* add labels to other selects

* make international tel codes a static object

* add component to storybook

* Update src/lib/international-telephone-codes.ts

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* update to new geo hook

* use Intl.DisplayNames, add polyfill

* use in rather than keys().includes()

---------

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>
This commit is contained in:
Samuel Newman
2025-12-10 22:12:30 +02:00
committed by GitHub
parent 07e1b3a0b6
commit 6ccda945e5
280 changed files with 1995 additions and 112 deletions
+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
}