"use client"; import { createContext, useContext, useCallback, type ReactNode, } from "react"; export type Locale = "zh" | "en"; const LOCALES: Locale[] = ["zh", "en"]; const DEFAULT_LOCALE: Locale = "zh"; type Messages = Record; type LocaleContextValue = { locale: Locale; messages: Messages; t: (key: string) => string; setLocale: (locale: Locale) => void; }; const LocaleContext = createContext(null); function getNested(obj: unknown, path: string): string | undefined { const keys = path.split("."); let current: unknown = obj; for (const key of keys) { if (current == null || typeof current !== "object") return undefined; current = (current as Record)[key]; } return typeof current === "string" ? current : undefined; } export function LocaleProvider({ locale, messages, children, }: { locale: Locale; messages: Messages; children: ReactNode; }) { const t = useCallback( (key: string) => { const value = getNested(messages, key); return value ?? key; }, [messages] ); const setLocale = useCallback((newLocale: Locale) => { const path = window.location.pathname; const newPath = path.replace(/^\/(zh|en)/, `/${newLocale}`); void import("@/app/lib/navigation-loading").then(({ startNavigation }) => { startNavigation(); window.location.href = newPath || `/${newLocale}/digital`; }); }, []); const value: LocaleContextValue = { locale, messages, t, setLocale, }; return ( {children} ); } export function useLocale() { const ctx = useContext(LocaleContext); if (!ctx) throw new Error("useLocale must be used within LocaleProvider"); return ctx.locale; } export function useTranslation(namespace?: string) { const ctx = useContext(LocaleContext); if (!ctx) throw new Error("useTranslation must be used within LocaleProvider"); return { t: (key: string) => { const fullKey = namespace ? `${namespace}.${key}` : key; return ctx.t(fullKey); }, }; } export function useLocaleRouter() { const locale = useLocale(); return { replace: (pathname: string, opts?: { locale?: Locale }) => { const newLocale = opts?.locale ?? locale; const cleanPath = pathname.replace(/^\/(zh|en)/, "") || "/"; const digitalPath = cleanPath.startsWith("/digital") ? cleanPath : `/digital${cleanPath === "/" ? "" : cleanPath}`; const newPath = `/${newLocale}${digitalPath}`; void import("@/app/lib/navigation-loading").then(({ startNavigation }) => { startNavigation(); window.location.href = newPath; }); }, }; } export { LOCALES, DEFAULT_LOCALE };