import { createContext, use, useCallback, useMemo, useState, type ReactNode } from "react"; /** * App-owned locale state. app-shell has no locale setter — the app holds the * locale, passes it to ``, and persists it. Changing it * re-renders the tree and re-resolves every `useT()` / `meta.title`. */ export type AppLocale = "en" | "ja"; const STORAGE_KEY = "app-locale"; const SUPPORTED: AppLocale[] = ["en", "ja"]; function readInitialLocale(): AppLocale { try { const saved = localStorage.getItem(STORAGE_KEY); if (saved === "en" || saved === "ja") return saved; } catch { // localStorage may be unavailable (opaque origin) — fall through to default. } return "en"; } interface LocaleContextValue { locale: AppLocale; setLocale: (next: AppLocale) => void; supported: AppLocale[]; } const LocaleContext = createContext(null); export const LocaleProvider = ({ children }: { children: ReactNode }) => { const [locale, setLocale] = useState(readInitialLocale); const changeLocale = useCallback((next: AppLocale) => { try { localStorage.setItem(STORAGE_KEY, next); } catch { // Persistence is best-effort; still switch in-memory. } setLocale(next); }, []); const value = useMemo( () => ({ locale, setLocale: changeLocale, supported: SUPPORTED }), [locale, changeLocale], ); return {children}; }; export function useAppLocale(): LocaleContextValue { const ctx = use(LocaleContext); if (!ctx) throw new Error("useAppLocale must be used within a LocaleProvider"); return ctx; }