Merge branch 'IDTEAM-1.26.0' into 'main'
[ProtonMail-WebClient.git] / packages / pass / lib / i18n / service.ts
blob71172847f070775806f77864967d3b6f9d414289
1 import type { Maybe, MaybePromise } from '@proton/pass/types';
2 import { logger } from '@proton/pass/utils/logger';
3 import type { Subscriber } from '@proton/pass/utils/pubsub/factory';
4 import { createPubSub } from '@proton/pass/utils/pubsub/factory';
5 import { DEFAULT_LOCALE } from '@proton/shared/lib/constants';
6 import { localeCode } from '@proton/shared/lib/i18n';
7 import { getClosestLocaleCode, getLanguageCode } from '@proton/shared/lib/i18n/helper';
8 import { loadDateLocale, loadLocale } from '@proton/shared/lib/i18n/loadLocale';
9 import { setTtagLocales } from '@proton/shared/lib/i18n/locales';
10 import { type TtagLocaleMap } from '@proton/shared/lib/interfaces/Locale';
11 import noop from '@proton/utils/noop';
13 type I18nServiceOptions = {
14     locales: TtagLocaleMap;
15     loadDateLocale: boolean;
16     getLocale: () => MaybePromise<Maybe<string>>;
17     onLocaleChange?: (locale: string) => void;
20 type LocaleEvent = { locale: string };
22 export const createI18nService = (options: I18nServiceOptions) => {
23     setTtagLocales(options.locales);
24     const pubsub = createPubSub<LocaleEvent>();
26     const hasRegion = (locale: string) => /[_-]/.test(locale);
28     const getFallbackLocale = (): string => {
29         const [fst, snd] = navigator.languages;
30         if (!fst && !snd) return DEFAULT_LOCALE;
32         return !hasRegion(fst) && hasRegion(snd) && getLanguageCode(fst) === getLanguageCode(snd) ? snd : fst;
33     };
35     const getLocale = async () => (await options.getLocale()) ?? getFallbackLocale();
37     const setLocale = async (locale?: string) => {
38         try {
39             const nextLocale = getClosestLocaleCode(locale ?? (await getLocale()), options.locales);
41             if (options.loadDateLocale) await loadDateLocale(nextLocale).catch(noop);
43             await loadLocale(nextLocale, options.locales);
44             options.onLocaleChange?.(nextLocale);
45             pubsub.publish({ locale: nextLocale });
47             if (nextLocale !== localeCode) logger.info(`[I18nService] changing locale to ${locale}`);
48         } catch {}
49     };
51     return {
52         setLocale,
53         getLocale,
54         getFallbackLocale,
55         subscribe: (fn: Subscriber<LocaleEvent>) => pubsub.subscribe(fn),
56         unsubscribe: () => pubsub.unsubscribe(),
57     };
60 export type I18nService = ReturnType<typeof createI18nService>;