47 lines
1.2 KiB
TypeScript
47 lines
1.2 KiB
TypeScript
import {
|
|
DEFAULT_LOCALE,
|
|
detectBrowserLocale,
|
|
initI18n,
|
|
isSupportedLocale,
|
|
type SupportedLocale,
|
|
} from '@chat-app/shared/i18n';
|
|
|
|
const LOCAL_STORAGE_KEY = 'chatapp.locale';
|
|
|
|
export function getCachedLocale(): SupportedLocale | null {
|
|
try {
|
|
const raw = window.localStorage.getItem(LOCAL_STORAGE_KEY);
|
|
return isSupportedLocale(raw) ? raw : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function cacheLocale(locale: SupportedLocale): void {
|
|
try {
|
|
window.localStorage.setItem(LOCAL_STORAGE_KEY, locale);
|
|
} catch {
|
|
// Ignore (private mode, quota, etc.). Profile row remains source of truth.
|
|
}
|
|
}
|
|
|
|
// Precedence for the very first paint (before we know the user):
|
|
// 1. cached choice from a previous session
|
|
// 2. navigator language(s)
|
|
// 3. DEFAULT_LOCALE (en)
|
|
export function resolveInitialLocale(): SupportedLocale {
|
|
return (
|
|
getCachedLocale() ??
|
|
detectBrowserLocale(typeof navigator !== 'undefined' ? navigator.languages : undefined) ??
|
|
DEFAULT_LOCALE
|
|
);
|
|
}
|
|
|
|
export function bootstrapI18n(): void {
|
|
const initialLocale = resolveInitialLocale();
|
|
initI18n({
|
|
initialLocale,
|
|
onLanguageChanged: (locale) => cacheLocale(locale),
|
|
});
|
|
}
|