// i18n.ts — 穿山甲 Web 用户中心 · 双语字串(单显,绝不并排) // 直接承袭 design/ui_kits/usercenter/ucparts.jsx 的 UCSTRINGS,并补充设置/设备/TOTP 键。 export type Lang = 'zh' | 'en'; type Entry = { zh: string; en: string }; export const STRINGS: Record = { navOverview: { zh: '概览', en: 'Overview' }, navSub: { zh: '订阅', en: 'Subscription' }, navRedeem: { zh: '兑换 & 购买', en: 'Redeem & buy' }, navInvite: { zh: '邀请返利', en: 'Referral' }, navSettings: { zh: '设置', en: 'Settings' }, signOut: { zh: '退出', en: 'Sign out' }, /* login */ loginTitle: { zh: '登录用户中心', en: 'Log in to your account' }, loginSub: { zh: '管理订阅、兑换激活码、查看用量', en: 'Manage subscription, redeem codes, track usage' }, emailLabel: { zh: '邮箱', en: 'Email' }, emailPh: { zh: '你的邮箱地址', en: 'your@email.com' }, pwLabel: { zh: '密码', en: 'Password' }, pwPh: { zh: '输入密码', en: 'Enter password' }, doLogin: { zh: '登录', en: 'Log in' }, forgotPw: { zh: '忘记密码?', en: 'Forgot password?' }, noAccount: { zh: '没有账户?在 App 内注册', en: 'No account? Sign up in the app' }, loginFailed: { zh: '邮箱或密码错误', en: 'Wrong email or password' }, loginLocked: { zh: '失败次数过多,账户已临时锁定', en: 'Too many attempts — account temporarily locked' }, lockedCountdown: { zh: '请于 {s} 秒后重试', en: 'Try again in {s}s' }, /* overview */ greeting: { zh: '欢迎回来', en: 'Welcome back' }, curPlan: { zh: '当前套餐', en: 'Current plan' }, freePlan: { zh: '免费版', en: 'Free' }, proMember: { zh: 'PRO 会员', en: 'PRO member' }, expires: { zh: '有效期至', en: 'Expires' }, renew: { zh: '续费 / 升级', en: 'Renew / Upgrade' }, quotaToday: { zh: '今日剩余时长', en: 'Time left today' }, dataToday: { zh: '今日已用流量', en: 'Data used today' }, devices: { zh: '在线设备', en: 'Devices online' }, quotaFree: { zh: '免费版 · 每日 10 分钟', en: 'Free · 10 min/day' }, usageTitle: { zh: '近 7 日流量 (GB)', en: 'Last 7 days (GB)' }, quickSub: { zh: '快速操作', en: 'Quick actions' }, qaSub: { zh: '获取订阅链接', en: 'Get subscription' }, qaRedeem: { zh: '兑换激活码', en: 'Redeem a code' }, qaApp: { zh: '下载 App', en: 'Download apps' }, /* subscription */ subTitle: { zh: '我的订阅', en: 'My subscription' }, subDesc: { zh: '订阅链接是你的专属凭证,泄露后他人可使用你的额度。请勿分享。', en: 'Your subscription link is a private credential. Never share it.' }, subCopy: { zh: '复制链接', en: 'Copy link' }, subCopied: { zh: '已复制', en: 'Copied' }, subReset: { zh: '重置链接', en: 'Reset link' }, subResetSub: { zh: '旧链接立即失效,所有设备需重新导入', en: 'Old link stops working; re-import on all devices' }, subResetOk: { zh: '已重置,请重新导入', en: 'Reset — re-import on your devices' }, scanTitle: { zh: '扫码导入', en: 'Scan to import' }, scanSub: { zh: '用穿山甲 App 或三方客户端扫码', en: 'Scan with the Pangolin app or a 3rd-party client' }, importTitle: { zh: '一键导入三方客户端', en: 'One-tap import' }, importSub: { zh: '已安装对应客户端时,点击即自动导入订阅。', en: 'If the client is installed, tapping imports the subscription automatically.' }, fmtNote: { zh: '同一链接同时兼容 sing-box / Clash.Meta / v2ray 格式。', en: 'One link serves sing-box / Clash.Meta / v2ray formats.' }, /* redeem */ redeemTitle: { zh: '兑换激活码', en: 'Redeem a code' }, redeemPh: { zh: '输入激活码', en: 'Enter activation code' }, redeemBtn: { zh: '激活', en: 'Redeem' }, redeemOk: { zh: '激活成功 · 套餐已到账', en: 'Activated — plan applied' }, buyTitle: { zh: '购买渠道', en: 'Where to buy' }, buySub: { zh: '本站不直接收款。通过以下渠道购买激活码,回到本页兑换即可:', en: 'We never take payment on this site. Buy a code via a channel below, then redeem here:' }, chStore: { zh: '自助发卡商店', en: 'Self-serve store' }, chStoreSub: { zh: '支付宝 / 微信 · 自动发码', en: 'Alipay / WeChat · instant code' }, chUsdtSub: { zh: '链上转账 · 最隐私 · 自动发码', en: 'On-chain · most private · instant code' }, chEmail: { zh: '邮箱客服', en: 'Email support' }, /* invite */ inviteTitle: { zh: '邀请返利', en: 'Referral' }, inviteSub: { zh: '好友通过你的链接注册并付费,你获得其首单 20% 余额返利,可抵扣续费。', en: 'When a friend signs up and pays via your link, you earn 20% of their first order as credit.' }, inviteLink: { zh: '我的邀请链接', en: 'My invite link' }, invited: { zh: '已邀请', en: 'Invited' }, paidUsers: { zh: '已付费', en: 'Converted' }, earned: { zh: '累计返利', en: 'Credit earned' }, inviteRecord: { zh: '邀请记录', en: 'History' }, recEmpty: { zh: '暂无邀请记录', en: 'No referrals yet' }, recRegistered: { zh: '已注册', en: 'Registered' }, recPaid: { zh: '已付费', en: 'Paid' }, /* 2FA login step */ twoFATitle: { zh: '双重认证', en: 'Two-factor auth' }, twoFAHint: { zh: '你的账户已开启双重认证。请输入身份验证器 App 中的 6 位动态码。', en: 'Two-factor auth is on for this account. Enter the 6-digit code from your authenticator app.' }, twoFAConfirm: { zh: '验证并登录', en: 'Verify & log in' }, twoFABack: { zh: '返回上一步', en: 'Back' }, twoFAWrong: { zh: '动态码不正确,请重试', en: 'Invalid code, try again' }, /* settings */ settingsTitle: { zh: '设置', en: 'Settings' }, prefTitle: { zh: '偏好', en: 'Preferences' }, prefLang: { zh: '显示语言', en: 'Language' }, prefTheme: { zh: '外观主题', en: 'Theme' }, themeLight: { zh: '浅色', en: 'Light' }, themeDark: { zh: '深色', en: 'Dark' }, /* devices */ devTitle: { zh: '设备管理', en: 'Devices' }, devSub: { zh: '管理已登录本账户的设备,移除后该设备需重新登录。', en: 'Devices signed in to your account. Removing one signs it out.' }, devCurrent: { zh: '当前设备', en: 'This device' }, devLastActive: { zh: '最近活跃', en: 'Last active' }, devRemove: { zh: '移除', en: 'Remove' }, devRemoveConfirmTitle: { zh: '移除此设备?', en: 'Remove this device?' }, devRemoveConfirmSub: { zh: '该设备将被登出,需重新输入凭证才能再次连接。', en: 'It will be signed out and must re-authenticate to connect again.' }, devEmpty: { zh: '暂无其他设备', en: 'No devices yet' }, cancel: { zh: '取消', en: 'Cancel' }, confirm: { zh: '确认移除', en: 'Remove' }, /* TOTP management */ totpTitle: { zh: '双重认证 (TOTP)', en: 'Two-factor auth (TOTP)' }, totpOff: { zh: '未开启', en: 'Off' }, totpOn: { zh: '已开启', en: 'On' }, totpDesc: { zh: '用身份验证器 App 生成的一次性动态码保护登录,显著提升账户安全。', en: 'Protect sign-in with one-time codes from an authenticator app.' }, totpEnable: { zh: '开启双重认证', en: 'Enable 2FA' }, totpDisableBtn: { zh: '关闭双重认证', en: 'Disable 2FA' }, totpStep1: { zh: '1. 用身份验证器扫码,或手动输入密钥', en: '1. Scan with an authenticator, or enter the key manually' }, totpSecretLabel: { zh: '手动密钥', en: 'Manual key' }, totpStep2: { zh: '2. 输入 App 显示的 6 位动态码以确认', en: '2. Enter the 6-digit code shown in the app to confirm' }, totpVerifyBtn: { zh: '确认开启', en: 'Confirm & enable' }, totpEnabledOk: { zh: '双重认证已开启', en: 'Two-factor auth enabled' }, totpDisabledOk: { zh: '双重认证已关闭', en: 'Two-factor auth disabled' }, totpDisableHint: { zh: '输入当前动态码以关闭双重认证。', en: 'Enter your current code to disable 2FA.' }, copyKey: { zh: '复制密钥', en: 'Copy key' }, /* generic errors */ errNetwork: { zh: '网络异常,请稍后重试', en: 'Network error, please retry' }, errUnknown: { zh: '操作失败,请稍后重试', en: 'Something went wrong, please retry' }, loading: { zh: '加载中…', en: 'Loading…' }, }; export type TFn = (key: string, vars?: Record) => string; export function makeT(lang: Lang): TFn { return (key, vars) => { const e = STRINGS[key]; let s = e ? e[lang] || key : key; if (vars) for (const k of Object.keys(vars)) s = s.replace(`{${k}}`, String(vars[k])); return s; }; }