UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

140 lines (138 loc) • 4.99 kB
import { matchLocale, readAcceptLanguage, readLocaleCookie, resolveLocale, serializeLocaleCookie } from "./locale.mjs"; import { createMessageCatalogs } from "./message-catalogs.mjs"; import { setupI18n } from "@lingui/core"; import { I18nProvider, Trans, useLingui } from "@lingui/react"; import { createContext, useCallback, useContext, useEffect, useMemo, useSyncExternalStore } from "react"; import { jsx } from "react/jsx-runtime"; //#region src/ui/i18n.tsx const SharedLocaleContext = createContext(null); const browserStores = /* @__PURE__ */ new Map(); function createLocaleStore(initialLocale) { let locale = initialLocale; const listeners = /* @__PURE__ */ new Set(); return { get: () => locale, set: (nextLocale) => { if (nextLocale === locale) return; locale = nextLocale; for (const listener of listeners) listener(); }, subscribe: (listener) => { listeners.add(listener); return () => listeners.delete(listener); } }; } function createLocaleRuntime({ locales, defaultLocale, cookieName }) { const LocaleContext = createContext(null); const getBrowserLocales = () => { if (typeof navigator === "undefined") return []; if (Array.isArray(navigator.languages)) return navigator.languages; return navigator.language ? [navigator.language] : []; }; const detectLocale = (preferredLocale) => resolveLocale({ preferredLocale, cookie: typeof document === "undefined" ? "" : document.cookie, browserLocales: getBrowserLocales(), locales, defaultLocale, cookieName }); const getStore = (initialLocale) => { const initial = matchLocale(initialLocale, locales) ?? detectLocale(); if (typeof window === "undefined") return createLocaleStore(initial); const existing = browserStores.get(cookieName); if (existing) return existing; const store = createLocaleStore(initial); browserStores.set(cookieName, store); return store; }; function LocaleProvider({ children, messages, initialLocale, preferredLocale, onLocaleChange }) { const parent = useContext(SharedLocaleContext); const sharedParent = parent?.cookieName === cookieName ? parent : null; const resolvedInitial = matchLocale(preferredLocale, locales) ?? matchLocale(initialLocale, locales) ?? matchLocale(sharedParent?.locale, locales); const serverLocale = resolvedInitial ?? defaultLocale; const store = useMemo(() => getStore(resolvedInitial), []); const locale = useSyncExternalStore(store.subscribe, store.get, () => serverLocale); const i18n = useMemo(() => setupI18n({ locale, messages: { [locale]: messages(locale) } }), [locale, messages]); useEffect(() => { if (sharedParent) return; const resolved = matchLocale(preferredLocale, locales); if (resolved) { Reflect.set(document, "cookie", serializeLocaleCookie(cookieName, resolved, window.location.protocol === "https:")); store.set(resolved); } }, [ preferredLocale, sharedParent, store ]); useEffect(() => { if (sharedParent) return; const previousLocale = document.documentElement.lang; document.documentElement.lang = locale; return () => { document.documentElement.lang = previousLocale; }; }, [locale, sharedParent]); const selectLocale = useCallback(async (nextLocale) => { if (!locales.includes(nextLocale)) return; if (sharedParent && !onLocaleChange) { await sharedParent.selectLocale(nextLocale); return; } if (onLocaleChange) await onLocaleChange(nextLocale); if (typeof document !== "undefined") Reflect.set(document, "cookie", serializeLocaleCookie(cookieName, nextLocale, typeof window !== "undefined" && window.location.protocol === "https:")); store.set(nextLocale); }, [ onLocaleChange, sharedParent, store ]); const value = useMemo(() => ({ locale, selectLocale }), [locale, selectLocale]); const sharedValue = useMemo(() => ({ cookieName, locale, selectLocale: async (next) => { const matched = matchLocale(next, locales); if (matched) await selectLocale(matched); } }), [locale, selectLocale]); return /* @__PURE__ */ jsx(SharedLocaleContext.Provider, { value: sharedValue, children: /* @__PURE__ */ jsx(LocaleContext.Provider, { value, children: /* @__PURE__ */ jsx(I18nProvider, { i18n, children }) }) }); } function useLocale() { const value = useContext(LocaleContext); if (!value) throw new Error("useLocale must be used within LocaleProvider"); return value; } function useTranslation() { const { _ } = useLingui(); return useCallback((id, values) => _(id, values), [_]); } const getLocale = () => matchLocale(browserStores.get(cookieName)?.get(), locales) ?? detectLocale(); return { LocaleProvider, useLocale, useTranslation, detectLocale, getLocale }; } //#endregion export { Trans, createLocaleRuntime, createMessageCatalogs, matchLocale, readAcceptLanguage, readLocaleCookie, resolveLocale, serializeLocaleCookie }; //# sourceMappingURL=i18n.mjs.map