hyapp-admin-platform/external-admin/src/i18n/ExternalI18nProvider.jsx

69 lines
2.4 KiB
JavaScript

import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
import {
DEFAULT_EXTERNAL_LOCALE,
EXTERNAL_LANGUAGE_OPTIONS,
EXTERNAL_LOCALE_STORAGE_KEY,
externalDirection,
externalMessage,
normalizeExternalLocale
} from "./messages.js";
const defaultTranslate = (key, values) => interpolate(externalMessage(DEFAULT_EXTERNAL_LOCALE, key), values);
const ExternalI18nContext = createContext({
direction: "ltr",
languages: EXTERNAL_LANGUAGE_OPTIONS,
locale: DEFAULT_EXTERNAL_LOCALE,
setLocale: () => {},
t: defaultTranslate
});
export function ExternalI18nProvider({ children }) {
// The product default is deliberately English. Browser language is ignored until the operator explicitly chooses and persists another locale.
const [locale, setLocaleState] = useState(readPersistedLocale);
const direction = externalDirection(locale);
const setLocale = useCallback((nextLocale) => {
const normalized = normalizeExternalLocale(nextLocale);
setLocaleState(normalized);
try {
globalThis.localStorage?.setItem(EXTERNAL_LOCALE_STORAGE_KEY, normalized);
} catch {
// Storage can be unavailable in hardened/private browser contexts; the in-memory locale still changes for the current session.
}
}, []);
const t = useCallback((key, values) => interpolate(externalMessage(locale, key), values), [locale]);
useEffect(() => {
// Keep native controls, assistive technology, MUI portals and the shell aligned when Arabic changes writing direction.
const root = globalThis.document?.documentElement;
if (!root) {
return;
}
root.lang = locale;
root.dir = direction;
globalThis.document.body?.setAttribute("dir", direction);
}, [direction, locale, t]);
const value = useMemo(
() => ({ direction, languages: EXTERNAL_LANGUAGE_OPTIONS, locale, setLocale, t }),
[direction, locale, setLocale, t]
);
return <ExternalI18nContext.Provider value={value}>{children}</ExternalI18nContext.Provider>;
}
export function useExternalI18n() {
return useContext(ExternalI18nContext);
}
function readPersistedLocale() {
try {
return normalizeExternalLocale(globalThis.localStorage?.getItem(EXTERNAL_LOCALE_STORAGE_KEY));
} catch {
return DEFAULT_EXTERNAL_LOCALE;
}
}
function interpolate(message, values = {}) {
return String(message).replace(/\{(\w+)\}/g, (match, key) => (values[key] === undefined ? match : String(values[key])));
}