import React, { createContext, useCallback, useContext, useMemo, useState, } from "react"; export type Lang = "zh-TW" | "zh-CN" | "en"; type Dict = Record; const dict: Record = { "zh-TW": { brand: "ARK 資料庫", mainNav: "網站導覽", home: "首頁", all: "全部資料", categories: "分類瀏覽", latest: "最新更新", official: "官方推薦", popular: "熱門資料", favorites: "我的收藏", search: "搜尋", searchPlaceholder: "搜尋資料...", searchNow: "立即搜尋資料", viewAll: "查看全部", heroTitle: "ARK 官方資料庫", heroSub: "集中、分類、管理 ARK 資料庫,讓你快速找到所需資源,推動社群共識與成長。", categorySection: "資料分類", officialSection: "官方推薦", latestSection: "最新更新", popularSection: "熱門資料", preview: "預覽", download: "下載", favorite: "收藏", 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_TW: "繁體中文", lang_zh_CN: "简体中文", lang_en: "English", filterAll: "全部", sortPublished: "發布時間", type_ppt: "PPT", 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: "載入中…", favoritesEmpty: "尚未加入收藏。", paginationPrev: "上一頁", paginationNext: "下一頁", listRange: "顯示 {{from}}–{{to}},共 {{total}} 筆", pageIndicator: "{{c}} / {{p}} 頁", resourceLangFilter: "資料語言", filterTagClear: "清除標籤", filterLanguageAll: "全部語言", aboutTitle: "關於本站", aboutIntro: "ARK 資料庫彙整官方教材、公告、影片與常用檔案,協助社群快速取得一致版本的可信內容。\n\n本站僅作展示與索引;資料權利仍以官方公告為準。", footerAbout: "關於本站", footerAdminLogin: "管理員登入", adminSearchLogs: "搜尋紀錄", adminMetricShares: "分享", adminSearchQuery: "查詢詞", adminSearchTime: "時間", adminSearchId: "編號", }, "zh-CN": { brand: "ARK 数据库", mainNav: "网站导航", home: "首页", all: "全部资料", categories: "分类浏览", latest: "最新更新", official: "官方推荐", popular: "热门资料", favorites: "我的收藏", search: "搜索", searchPlaceholder: "搜索资料...", searchNow: "立即搜索资料", viewAll: "查看全部", heroTitle: "ARK 官方数据库", heroSub: "集中、分类、管理 ARK 数据库,让你快速找到所需资源,推动社群共识与成长。", categorySection: "资料分类", officialSection: "官方推荐", latestSection: "最新更新", popularSection: "热门资料", preview: "预览", download: "下载", favorite: "收藏", 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_TW: "繁体中文", lang_zh_CN: "简体中文", lang_en: "English", filterAll: "全部", sortPublished: "发布时间", type_ppt: "PPT", 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: "加载中…", favoritesEmpty: "还没有收藏。", paginationPrev: "上一页", paginationNext: "下一页", listRange: "显示 {{from}}–{{to}},共 {{total}} 条", pageIndicator: "{{c}} / {{p}} 页", resourceLangFilter: "资料语言", filterTagClear: "清除标签", filterLanguageAll: "全部语言", aboutTitle: "关于本站", aboutIntro: "ARK 数据库汇总官方教材、公告、视频与常用文件,帮助社区快速获取一致版本的可信内容。\n\n本站仅供展示与索引;权利归属以官方公告为准。", footerAbout: "关于本站", footerAdminLogin: "管理员登录", adminSearchLogs: "搜索记录", adminMetricShares: "分享", adminSearchQuery: "查询词", adminSearchTime: "时间", adminSearchId: "编号", }, en: { brand: "ARK Library", mainNav: "Site menu", home: "Home", all: "All assets", categories: "Categories", latest: "Latest", official: "Official picks", popular: "Popular", favorites: "Favorites", 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", favorite: "Favorite", 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_TW: "Traditional Chinese", lang_zh_CN: "Simplified Chinese", lang_en: "English", filterAll: "All types", sortPublished: "Published date", type_ppt: "PPT", 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…", favoritesEmpty: "No favorites yet.", 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", }, }; /** Fixed locale lookup (for admin UI always in Traditional Chinese). */ export function tLang(lang: Lang, key: string): string { return dict[lang][key] || dict["zh-TW"][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) as Lang | null; if (s === "zh-CN" || s === "en" || s === "zh-TW") return s; return "zh-TW"; }); const setLang = (l: Lang) => { localStorage.setItem(LANG_KEY, l); setLangState(l); }; const t = useCallback( (k: string) => dict[lang][k] || dict["zh-TW"][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) { if (lang === "zh-TW") return "zh-TW"; if (lang === "zh-CN") return "zh-CN"; return "en"; }