import React, { createContext, useCallback, useContext, useMemo, useState, } from "react"; export type Lang = "zh-CN" | "en" | "ja" | "ko" | "vi" | "id" | "ms"; type Dict = Record; const zhDict: Dict = { brand: "ARK 数据库", mainNav: "网站导航", home: "首页", all: "全部资料", categories: "分类浏览", latest: "最新更新", official: "官方推荐", popular: "热门资料", search: "搜索", searchPlaceholder: "搜索资料...", searchNow: "立即搜索资料", viewAll: "查看全部", heroTitle: "ARK 官方数据库", heroSub: "集中、分类、管理 ARK 数据库,让你快速找到所需资源,推动社群共识与成长。", categorySection: "资料分类", officialSection: "官方推荐", latestSection: "最新更新", popularSection: "热门资料", preview: "预览", download: "下载", share: "分享", profile: "个人中心", langLabel: "语言", admin: "后台", login: "登录", logout: "退出", email: "邮箱", password: "密码", dashboard: "仪表盘", resources: "资料管理", newResource: "新增资料", save: "保存", title: "标题", description: "简介", type: "类型", language: "语言", category: "分类", status: "状态", public: "公开", downloadable: "可下载", recommended: "首页推荐", cover: "封面图 URL", fileUrl: "文件 URL", externalUrl: "外部链接", body: "文案内容", badge: "推荐标签", published: "已发布", draft: "草稿", archived: "归档", noResults: "找不到符合的资料,请换个关键字或浏览分类。", copyLink: "复制链接", related: "相关资料", total: "总资料", views: "浏览", downloads: "下载", wallet: "钱包", walletPageTitle: "钱包登录", walletPageIntro: "连接 Web3 钱包以使用会员相关功能。采用标准签名登录,不发送交易、不消耗 gas。", walletStepExtension: "电脑已安装浏览器扩展钱包(如 MetaMask)时,可直接连接。", walletStepQR: "电脑未安装钱包时:在连接窗口选择 WalletConnect,用手机钱包扫描 QR Code。", walletStepSign: "连接成功后,点击「签署登录」并在钱包内签名即可完成验证。", signInWallet: "签署登录", walletSignedIn: "已验证登录", walletLogout: "退出钱包", walletMissingProjectId: "请配置 VITE_WALLETCONNECT_PROJECT_ID(Reown Cloud),否则无法使用 WalletConnect/扫码。", walletSetupNeeded: "钱包扫码未启用(请在服务器配置环境变量)", lang_zh_CN: "中文", lang_en: "English", lang_ja: "日本語", lang_ko: "한국어", lang_vi: "Tiếng Việt", lang_id: "Bahasa Indonesia", lang_ms: "Bahasa Melayu", filterAll: "全部", sortPublished: "发布时间", type_ppt: "PPT", type_music: "音乐", type_video: "视频", type_image: "图片", type_pdf: "PDF", type_link: "链接", type_text: "文字", type_archive: "压缩包", type_zip: "ZIP", adminLoginTitle: "管理后台登录", adminEditResource: "编辑资料", adminVideoFileHint: "上传视频文件(MP4/WebM/MOV 等),类型请选择「视频」;保存后前台自动播放(默认静音,可点喇叭开声音)。", adminStatTodayNew: "今日新增", adminStatFavorites: "收藏", adminMetricDownloads: "下载", adminMetricFavorites: "收藏", adminMetricViews: "浏览", edit: "编辑", backToList: "返回列表", sortOrderLabel: "排序权重", previewUrlLabel: "预览网址", tagsCommaLabel: "标签(逗号分隔)", uploadFile: "上传文件", loading: "加载中…", paginationPrev: "上一页", paginationNext: "下一页", listRange: "显示 {{from}}–{{to}},共 {{total}} 条", pageIndicator: "{{c}} / {{p}} 页", resourceLangFilter: "资料语言", filterTagClear: "清除标签", filterLanguageAll: "全部语言", aboutTitle: "关于本站", aboutIntro: "ARK 数据库汇总官方教材、公告、视频与常用文件,帮助社区快速获取一致版本的可信内容。\n\n本站仅供展示与索引;权利归属以官方公告为准。", footerAbout: "关于本站", footerAdminLogin: "管理员登录", adminSearchLogs: "搜索记录", adminMetricShares: "分享", adminSearchQuery: "查询词", adminSearchTime: "时间", adminSearchId: "编号", }; const enDict: Dict = { brand: "ARK Library", mainNav: "Site menu", home: "Home", all: "All assets", categories: "Categories", latest: "Latest", official: "Official picks", popular: "Popular", search: "Search", searchPlaceholder: "Search resources...", searchNow: "Search now", viewAll: "View all", heroTitle: "ARK Official Library", heroSub: "Centralize, organize, and manage the ARK library so you can find what you need fast and help the community grow together.", categorySection: "Categories", officialSection: "Official recommendations", latestSection: "Latest updates", popularSection: "Popular assets", preview: "Preview", download: "Download", share: "Share", profile: "Profile", langLabel: "Language", admin: "Admin", login: "Sign in", logout: "Sign out", email: "Email", password: "Password", dashboard: "Dashboard", resources: "Resources", newResource: "New resource", save: "Save", title: "Title", description: "Description", type: "Type", language: "Language", category: "Category", status: "Status", public: "Public", downloadable: "Downloadable", recommended: "Featured", cover: "Cover image URL", fileUrl: "File URL", externalUrl: "External URL", body: "Text body", badge: "Badge label", published: "Published", draft: "Draft", archived: "Archived", noResults: "No results. Try another keyword or browse categories.", copyLink: "Copy link", related: "Related", total: "Total items", views: "Views", downloads: "Downloads", wallet: "Wallet", walletPageTitle: "Wallet sign-in", walletPageIntro: "Connect a Web3 wallet for member features. This uses a standard signed message — no transaction and no gas.", walletStepExtension: "On desktop with a browser extension (e.g. MetaMask), connect directly.", walletStepQR: "On desktop without an extension: choose WalletConnect in the modal and scan the QR code with your mobile wallet.", walletStepSign: 'After connecting, tap "Sign in" and approve the message in your wallet to verify.', signInWallet: "Sign in", walletSignedIn: "Signed in", walletLogout: "Disconnect", walletMissingProjectId: "Set VITE_WALLETCONNECT_PROJECT_ID (free on Reown Cloud). Required for WalletConnect / QR login.", walletSetupNeeded: "Wallet QR login disabled (set env on server)", lang_zh_CN: "Chinese", lang_en: "English", lang_ja: "Japanese", lang_ko: "Korean", lang_vi: "Vietnamese", lang_id: "Indonesian", lang_ms: "Malay", filterAll: "All types", sortPublished: "Published date", type_ppt: "PPT", type_music: "Music", type_video: "Video", type_image: "Image", type_pdf: "PDF", type_link: "Link", type_text: "Text", type_archive: "Archive", type_zip: "ZIP", adminLoginTitle: "Admin sign in", adminEditResource: "Edit resource", adminVideoFileHint: "Upload a video file (MP4/WebM/MOV, etc.) and set type to Video; the site will autoplay (muted by default — user can unmute).", adminStatTodayNew: "New today", adminStatFavorites: "Favorites", adminMetricDownloads: "Downloads", adminMetricFavorites: "Favorites", adminMetricViews: "Views", edit: "Edit", backToList: "Back to list", sortOrderLabel: "Sort order", previewUrlLabel: "Preview URL", tagsCommaLabel: "Tags (comma-separated)", uploadFile: "Upload", loading: "Loading…", paginationPrev: "Previous", paginationNext: "Next", listRange: "Showing {{from}}–{{to}} of {{total}}", pageIndicator: "Page {{c}} / {{p}}", resourceLangFilter: "Resource language", filterTagClear: "Clear tag", filterLanguageAll: "All languages", aboutTitle: "About this site", aboutIntro: "The ARK library brings together official decks, announcements, videos, and common files so the community can find consistent, trustworthy versions quickly.\n\nThis site is for discovery and indexing only; rights remain with official notices.", footerAbout: "About", footerAdminLogin: "Admin sign-in", adminSearchLogs: "Search logs", adminMetricShares: "Shares", adminSearchQuery: "Query", adminSearchTime: "Time", adminSearchId: "ID", }; const languageNames: Record = { "zh-CN": { lang_zh_CN: "中文", lang_en: "English", lang_ja: "日本語", lang_ko: "한국어", lang_vi: "Tiếng Việt", lang_id: "Bahasa Indonesia", lang_ms: "Bahasa Melayu", }, en: { lang_zh_CN: "Chinese", lang_en: "English", lang_ja: "Japanese", lang_ko: "Korean", lang_vi: "Vietnamese", lang_id: "Indonesian", lang_ms: "Malay", }, ja: { lang_zh_CN: "中国語", lang_en: "英語", lang_ja: "日本語", lang_ko: "韓国語", lang_vi: "ベトナム語", lang_id: "インドネシア語", lang_ms: "マレー語", }, ko: { lang_zh_CN: "중국어", lang_en: "영어", lang_ja: "일본어", lang_ko: "한국어", lang_vi: "베트남어", lang_id: "인도네시아어", lang_ms: "말레이어", }, vi: { lang_zh_CN: "Tiếng Trung", lang_en: "Tiếng Anh", lang_ja: "Tiếng Nhật", lang_ko: "Tiếng Hàn", lang_vi: "Tiếng Việt", lang_id: "Tiếng Indonesia", lang_ms: "Tiếng Mã Lai", }, id: { lang_zh_CN: "Bahasa Tionghoa", lang_en: "Bahasa Inggris", lang_ja: "Bahasa Jepang", lang_ko: "Bahasa Korea", lang_vi: "Bahasa Vietnam", lang_id: "Bahasa Indonesia", lang_ms: "Bahasa Melayu", }, ms: { lang_zh_CN: "Bahasa Cina", lang_en: "Bahasa Inggeris", lang_ja: "Bahasa Jepun", lang_ko: "Bahasa Korea", lang_vi: "Bahasa Vietnam", lang_id: "Bahasa Indonesia", lang_ms: "Bahasa Melayu", }, }; const dict: Record = { "zh-CN": { ...zhDict, ...languageNames["zh-CN"] }, en: { ...enDict, ...languageNames.en }, ja: { ...enDict, ...languageNames.ja }, ko: { ...enDict, ...languageNames.ko }, vi: { ...enDict, ...languageNames.vi }, id: { ...enDict, ...languageNames.id }, ms: { ...enDict, ...languageNames.ms }, }; /** Fixed locale lookup (admin UI uses Simplified Chinese). */ export function tLang(lang: Lang, key: string): string { return dict[lang][key] || dict.en[key] || key; } type Ctx = { lang: Lang; setLang: (l: Lang) => void; t: (k: string) => string }; const I18nCtx = createContext(null); const LANG_KEY = "ark_lang"; export function I18nProvider({ children }: { children: React.ReactNode }) { const [lang, setLangState] = useState(() => { const s = localStorage.getItem(LANG_KEY); if (s === "zh" || s === "zh-TW") return "zh-CN"; if ( s === "zh-CN" || s === "en" || s === "ja" || s === "ko" || s === "vi" || s === "id" || s === "ms" ) return s; return "en"; }); const setLang = (l: Lang) => { localStorage.setItem(LANG_KEY, l); setLangState(l); }; const t = useCallback( (k: string) => dict[lang][k] || dict.en[k] || k, [lang], ); const v = useMemo(() => ({ lang, setLang, t }), [lang, t]); return {children}; } export function useI18n() { const v = useContext(I18nCtx); if (!v) throw new Error("I18nProvider missing"); return v; } export function langQuery(lang: Lang) { return lang; }