chore(history): import initial web product snapshot

This commit is contained in:
wmq
2026-07-25 00:30:00 +08:00
commit cf0eed46c3
131 changed files with 15693 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
import { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from 'react'
import { UI_LOCALES, type UiLocale } from '@/config/languages'
import { zh, type LocaleDict } from './locales/zh'
import { en } from './locales/en'
import { ar } from './locales/ar'
const DICTS: Record<UiLocale, LocaleDict> = { zh, en, ar }
interface I18nContextValue {
locale: UiLocale
dir: 'ltr' | 'rtl'
setLocale: (l: UiLocale) => void
t: (key: keyof LocaleDict) => string
}
const I18nContext = createContext<I18nContextValue | null>(null)
const STORAGE_KEY = 'lx-locale'
export function I18nProvider({ children }: { children: ReactNode }) {
const [locale, setLocaleState] = useState<UiLocale>(() => {
const saved = localStorage.getItem(STORAGE_KEY)
return (saved === 'en' || saved === 'ar' || saved === 'zh' ? saved : 'zh') as UiLocale
})
const dir: 'ltr' | 'rtl' = UI_LOCALES.find((l) => l.code === locale)?.rtl ? 'rtl' : 'ltr'
useEffect(() => {
document.documentElement.lang = locale === 'zh' ? 'zh-CN' : locale
document.documentElement.dir = dir
localStorage.setItem(STORAGE_KEY, locale)
}, [locale, dir])
const value = useMemo<I18nContextValue>(
() => ({
locale,
dir,
setLocale: setLocaleState,
t: (key) => DICTS[locale][key] ?? zh[key] ?? String(key),
}),
[locale, dir],
)
return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>
}
export function useI18n(): I18nContextValue {
const ctx = useContext(I18nContext)
if (!ctx) throw new Error('useI18n must be used within I18nProvider')
return ctx
}