42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
/** Helpers for displaying geo database keys. */
|
|||
|
|
|
||
|
|
const displayNames = new Map<string, Intl.DisplayNames>()
|
||
|
|
|
||
|
|
function names(lang: string): Intl.DisplayNames | null {
|
||
|
|
const locale = lang === 'zh' ? 'zh-CN' : 'en'
|
||
|
|
if (!displayNames.has(locale)) {
|
||
|
|
try {
|
||
|
|
displayNames.set(locale, new Intl.DisplayNames([locale], { type: 'region' }))
|
||
|
|
} catch {
|
||
|
|
return null
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return displayNames.get(locale) ?? null
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Localized country name for a two letter code, or null when the code is not a
|
||
|
|
* country. GeoIP databases also contain provider groups such as "cloudflare".
|
||
|
|
*/
|
||
|
|
export function regionName(code: string, lang: string): string | null {
|
||
|
|
if (!/^[a-z]{2}$/i.test(code)) return null
|
||
|
|
const upper = code.toUpperCase()
|
||
|
|
try {
|
||
|
|
const name = names(lang)?.of(upper)
|
||
|
|
return name && name !== upper ? name : null
|
||
|
|
} catch {
|
||
|
|
return null
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Flag emoji for a two letter country code, empty for anything else. */
|
||
|
|
export function flagOf(code: string): string {
|
||
|
|
if (!/^[a-z]{2}$/i.test(code)) return ''
|
||
|
|
const base = 0x1f1e6
|
||
|
|
const upper = code.toUpperCase()
|
||
|
|
return String.fromCodePoint(
|
||
|
|
base + upper.charCodeAt(0) - 65,
|
||
|
|
base + upper.charCodeAt(1) - 65,
|
||
|
|
)
|
||
|
|
}
|