"use client"; import { NextIntlClientProvider } from "next-intl"; import { useEffect, useState } from "react"; import { DEFAULT_LOCALE, LOCALE_STORAGE_KEY, Locale, detectBrowserLocale, isLocale } from "./config"; // #352 — 메시지 파일을 정적 import (Tree-shaking 가능, 클라이언트 번들에 4언어 모두 포함되지만 // 30개 키 수준이라 부담 미미. 키가 늘어나면 동적 import로 분할 검토) import ko from "@/messages/ko.json"; import en from "@/messages/en.json"; import ja from "@/messages/ja.json"; import es from "@/messages/es.json"; const MESSAGES: Record = { ko, en, ja, es }; interface LocaleContextValue { locale: Locale; setLocale: (l: Locale) => void; } import { createContext, useContext } from "react"; const LocaleContext = createContext(null); export function useLocale() { const ctx = useContext(LocaleContext); if (!ctx) throw new Error("useLocale must be used within LocaleProvider"); return ctx; } export function LocaleProvider({ children }: { children: React.ReactNode }) { // SSR 단계는 기본 로케일로 시작 (hydration mismatch 방지) const [locale, setLocaleState] = useState(DEFAULT_LOCALE); useEffect(() => { if (typeof window === "undefined") return; const saved = localStorage.getItem(LOCALE_STORAGE_KEY); const initial: Locale = isLocale(saved) ? saved : detectBrowserLocale(); if (initial !== locale) setLocaleState(initial); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const setLocale = (l: Locale) => { setLocaleState(l); if (typeof window !== "undefined") { localStorage.setItem(LOCALE_STORAGE_KEY, l); } }; return ( {children} ); }