You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.0 KiB
TypeScript
113 lines
3.0 KiB
TypeScript
import { en } from '../../localization/locales';
|
|
import type { LocalizerDictionary } from '../../types/Localizer';
|
|
import { timeLocaleMap } from './timeLocaleMap';
|
|
|
|
let mappedBrowserLocaleDisplayed = false;
|
|
let initialLocale: Locale | undefined;
|
|
|
|
let translationDictionary: LocalizerDictionary | undefined;
|
|
|
|
/**
|
|
* Only exported for testing, reset the dictionary to use for translations and the locale set
|
|
*/
|
|
export function resetLocaleAndTranslationDict() {
|
|
translationDictionary = undefined;
|
|
initialLocale = undefined;
|
|
}
|
|
|
|
/**
|
|
* Returns the current dictionary to use for translations.
|
|
*/
|
|
export function getTranslationDictionary(): LocalizerDictionary {
|
|
if (translationDictionary) {
|
|
return translationDictionary;
|
|
}
|
|
|
|
i18nLog('getTranslationDictionary: dictionary not init yet. Using en.');
|
|
return en;
|
|
}
|
|
|
|
export function getFallbackDictionary(): LocalizerDictionary {
|
|
return en;
|
|
}
|
|
|
|
/**
|
|
* Logs an i18n message to the console.
|
|
* @param message - The message to log.
|
|
*
|
|
*/
|
|
export function i18nLog(message: string) {
|
|
if (typeof window !== 'undefined') {
|
|
// eslint-disable-next-line no-console
|
|
(window?.log?.error ?? console.log)(`i18n: ${message}`);
|
|
} else {
|
|
// eslint-disable-next-line no-console
|
|
console.log(`i18n: ${message}`);
|
|
}
|
|
}
|
|
|
|
export type Locale = keyof typeof timeLocaleMap;
|
|
|
|
export function getTimeLocaleDictionary() {
|
|
return timeLocaleMap[getLocale()];
|
|
}
|
|
|
|
/**
|
|
* Returns the current locale.
|
|
*/
|
|
export function getLocale(): Locale {
|
|
if (!initialLocale) {
|
|
i18nLog(`getLocale: using initialLocale: ${initialLocale}`);
|
|
|
|
throw new Error('initialLocale is unset');
|
|
}
|
|
return initialLocale;
|
|
}
|
|
|
|
/**
|
|
* Returns the closest supported locale by the browser.
|
|
*/
|
|
export function getBrowserLocale() {
|
|
const userLocaleDashed = getLocale();
|
|
|
|
const matchinglocales = Intl.DateTimeFormat.supportedLocalesOf(userLocaleDashed);
|
|
const mappingTo = matchinglocales?.[0] || 'en';
|
|
|
|
if (!mappedBrowserLocaleDisplayed) {
|
|
mappedBrowserLocaleDisplayed = true;
|
|
i18nLog(`userLocaleDashed: '${userLocaleDashed}', mapping to browser locale: ${mappingTo}`);
|
|
}
|
|
|
|
return mappingTo;
|
|
}
|
|
|
|
export function setInitialLocale(locale: Locale, dictionary: LocalizerDictionary) {
|
|
if (translationDictionary) {
|
|
throw new Error('setInitialLocale: translationDictionary or initialLocale is already init');
|
|
}
|
|
translationDictionary = dictionary;
|
|
initialLocale = locale;
|
|
}
|
|
|
|
export function isLocaleSet() {
|
|
return initialLocale !== undefined;
|
|
}
|
|
|
|
export function getStringForCardinalRule(
|
|
localizedString: string,
|
|
cardinalRule: Intl.LDMLPluralRule
|
|
): string | undefined {
|
|
// TODO: investigate if this is the best way to handle regex like this
|
|
const cardinalPluralRegex: Record<Intl.LDMLPluralRule, RegExp> = {
|
|
zero: /zero \[(.*?)\]/g,
|
|
one: /one \[(.*?)\]/g,
|
|
two: /two \[(.*?)\]/g,
|
|
few: /few \[(.*?)\]/g,
|
|
many: /many \[(.*?)\]/g,
|
|
other: /other \[(.*?)\]/g,
|
|
};
|
|
const regex = cardinalPluralRegex[cardinalRule];
|
|
const match = regex.exec(localizedString);
|
|
return match?.[1] ?? undefined;
|
|
}
|