Files

119 lines
3.8 KiB
TypeScript

import type { Locale } from 'date-fns';
import type { CrowdinLocale } from '../../localization';
import { timeLocaleMap } from './timeLocaleMap';
import { isUnitTest } from '../../shared/env_vars';
let mappedBrowserLocaleDisplayed = false;
let crowdinLocale: CrowdinLocale | undefined;
let browserLocale: string | undefined;
/**
* Logs an i18n message to the console.
* @param message - The message to log.
* @deprecated we want to use a normal logger instead of this function, eventually.
*/
export function i18nLog(message: string) {
// eslint-disable-next-line no-console
console.log(`i18n: ${message}`);
}
export function getTimeLocaleDictionary() {
return (timeLocaleMap as Record<string, Locale>)[getBrowserLocale()] || timeLocaleMap.en;
}
/**
* Some users have a locale setup with a ':' in it.
* When this happens, the full locale (i.e. the part with the "_") can sometimes be on the left, sometimes on the right.
* This function will always return the part with the "_" if found, otherwise the full locale.
*/
export function keepFullLocalePart(locale: string) {
const firstUnderscore = locale.indexOf('_');
const firstDash = locale.indexOf('-');
const firstSemiColon = locale.indexOf(':');
if (firstSemiColon === -1) {
return locale;
}
const firstUnderscoreOrDash = Math.max(firstUnderscore, firstDash);
if (firstSemiColon > firstUnderscoreOrDash) {
// the semicolon is after the underscore, so we return the start of the string (de_DE:en we return de_DE)
return locale.substring(0, firstSemiColon);
}
// the semicolon is before the underscore, so we return the end of the string (in en:de_DE wew return de_DE)
return locale.substring(firstSemiColon + 1);
}
/**
* Returns the current locale as supported by Session (i.e. one generated by crowdin)
*/
export function getCrowdinLocale(): CrowdinLocale {
if (!crowdinLocale) {
i18nLog(`getCrowdinLocale: ${crowdinLocale}`);
throw new Error('crowdinLocale is unset');
}
return crowdinLocale;
}
/**
* Returns the closest supported locale by the browser.
*/
function getInitialBrowserLocale() {
const parsedLocale = keepFullLocalePart(process.env.LANGUAGE || getCrowdinLocale() || 'en');
// supportedLocalesOf will throw if the locales has a '_' instead of a '-' in it.
const userLocaleDashed = parsedLocale.replaceAll('_', '-');
try {
let matchingLocales: Array<string> = [];
try {
matchingLocales = Intl.DateTimeFormat.supportedLocalesOf(userLocaleDashed);
} catch (innerError) {
// some users have a locale setup with a ':' in it.
// see https://github.com/oxen-io/session-desktop/issues/3221
const semiColonIndex = userLocaleDashed.indexOf(':');
if (semiColonIndex > -1) {
matchingLocales = Intl.DateTimeFormat.supportedLocalesOf(
userLocaleDashed.substring(0, semiColonIndex)
);
}
}
const mappingTo = matchingLocales?.[0] || 'en';
if (!mappedBrowserLocaleDisplayed) {
mappedBrowserLocaleDisplayed = true;
i18nLog(`userLocaleDashed: '${userLocaleDashed}', mapping to browser locale: ${mappingTo}`);
}
return mappingTo;
} catch (e) {
if (!mappedBrowserLocaleDisplayed) {
mappedBrowserLocaleDisplayed = true;
i18nLog(
`userLocaleDashed: '${userLocaleDashed}' was an invalid locale for supportedLocalesOf(). Falling back to 'en'. Error:${e.message} `
);
}
return 'en';
}
}
export function getBrowserLocale() {
if (!browserLocale) {
browserLocale = getInitialBrowserLocale();
}
return browserLocale;
}
export function setInitialLocale(crowdinLocaleArg: CrowdinLocale) {
if (crowdinLocale && !isUnitTest()) {
i18nLog('setInitialLocale: crowdinLocale is already init');
}
crowdinLocale = crowdinLocaleArg;
}
export function isSessionLocaleSet() {
return !!crowdinLocale;
}