How to define aliases of locales in typesafe-i18n?

431 Views Asked by At

Motivation

Chinese language has historically multiple language codes (RFC 5646 with ISO-639 zh). Practically, the most frequently used ones are zh-CN (for Simplified Hanzi Script of Chinese Mandarin language mainly used in PRC, etc.), zh-TW (for Traditional Hanzi Script of Chinese Mandarin language mainly used in Taiwan, etc.), zh (usually equivalent of zh-CN). There are also less used zh-HanS and zh-HanT that are almost share the same effect as zh-CN and zh-TW respectively with regions not specified.

The new ECMAScript Intl API will give different display names for all those codes, but will carry their semantically regional and political message. I want my application to be neutral so I would like to use zh-HanS and zh-HanT instead of zh-CN and zh-TW.

Problem

Most of modern browsers will always use Accept-Language: zh-CN; zh; for zh-CN/zh-HanS, and Accept-Language: zh-TW; zh; for zh-TW/zh-HanT in HTTP headers. Since zh-HanS/zh-HanT are not used, if I use them in my application as src/i18n/zh-HanS/src/i18n/zh-HanT, detectLocale(initAcceptLanguageHeaderDetector({headers}) of typesafe-i18n will fail to find the correct locale, tries to fallback to zh, but then fail and fallback to baseLocale (often en).

Question

How can I make aliases for them and let the detector fallback to the correct language?

1

There are 1 best solutions below

0
mkpoli On

The generated detectLocale function defined as following in src/i18n/i18n-util.ts will use locales (a generated variable showing a list of locale files).

// src/i18n/i18n-util.ts
import { detectLocale as detectLocaleFn } from 'typesafe-i18n/detectors'

// [...]

export const locales: Locales[] = [
    'en',
    'ja',
    'zh-HanS',
    'zh-HanT'
]

// [...]

export const detectLocale = (...detectors: LocaleDetector[]) => detectLocaleFn<Locales>(baseLocale, locales, ...detectors)

So we need to detectLocaleFn above intead (detectLocale from 'typesafe-i18n/detectors')

In your detection code,

import detectLocale from 'typesafe-i18n/detectors'

// [...]

// Alias table
const LOCALE_ALIAS = new Map<string, Locales>([
  ['zh-CN', 'zh-HanS'],
  ['zh-TW', 'zh-HanT'],
  ['zh-HK', 'zh-HanT'],
  ['zh', 'zh-HanS'],
])
// for initAcceptLanguageHeaderDetector
const headers = getHeaders(request)
const acceptLanguageDetector = initAcceptLanguageHeaderDetector({ headers })

// detection
const locale = detectLocale<Locales>(baseLocale, [...locales, ...LOCALE_ALIAS.keys()] as Locales[], acceptLanguageDetector)

const aliasedLocale = LOCALE_ALIAS.get(locale) ?? locale
console.log(`Detected locale: ${locale}, aliased to: ${aliasedLocale}`)