Files
sales-crm-dashboard/lib/i18n.tsx
2026-04-25 21:52:01 +08:00

60 lines
1.5 KiB
TypeScript

"use client"
import React, { createContext, useContext, useState, useCallback, useEffect } from "react"
import en from "@/locales/en.json"
import zh from "@/locales/zh.json"
type Locale = "en" | "zh"
const messages: Record<Locale, typeof en> = { en, zh }
interface I18nContextType {
locale: Locale
setLocale: (locale: Locale) => void
t: (key: string) => string
}
const I18nContext = createContext<I18nContextType | null>(null)
function getNestedValue(obj: any, path: string): string {
const value = path.split(".").reduce((acc, part) => acc?.[part], obj)
return typeof value === "string" ? value : Array.isArray(value) ? value.join(", ") : path
}
export function I18nProvider({ children }: { children: React.ReactNode }) {
const [locale, setLocaleState] = useState<Locale>("zh")
useEffect(() => {
const saved = localStorage.getItem("locale") as Locale | null
if (saved && (saved === "en" || saved === "zh")) {
setLocaleState(saved)
}
}, [])
const setLocale = useCallback((l: Locale) => {
setLocaleState(l)
localStorage.setItem("locale", l)
}, [])
const t = useCallback(
(key: string) => getNestedValue(messages[locale], key),
[locale]
)
return (
<I18nContext.Provider value={{ locale, setLocale, t }}>
{children}
</I18nContext.Provider>
)
}
export function useI18n() {
const ctx = useContext(I18nContext)
if (!ctx) throw new Error("useI18n must be used within I18nProvider")
return ctx
}
export function useTranslation() {
return useI18n()
}