thread-master/apps/web/src/lib/i18n/messages.ts

2716 lines
114 KiB
TypeScript
Raw Normal View History

2026-07-10 05:10:31 +00:00
import type { AppLocale } from "./types";
/** 扁平 key → 字串;{name} 可插值 */
export type MessageDict = Record<string, string>;
export const zhTW: MessageDict = {
"app.name": "巡樓",
"app.nameEn": "Lapras",
"app.nameZh": "巡樓",
"app.tagline": "Threads 海巡好幫手",
"app.taglineEn": "Patrol Threads with ease",
"nav.today": "今日",
"nav.crew": "帳號",
"nav.studio": "創作",
"nav.scout": "海巡",
"nav.outbox": "發送",
"nav.jobs": "任務",
"nav.brands": "品牌",
"nav.more": "更多",
"nav.moreTitle": "更多功能",
"nav.users": "島民管理",
"nav.usage": "用量與方案",
"nav.profile": "會員資料",
2026-07-10 12:54:45 +00:00
"nav.invite": "邀請關係",
2026-07-10 05:10:31 +00:00
"nav.settings": "系統設定",
"nav.logout": "登出",
"nav.navigate": "導覽",
"common.save": "儲存",
"common.cancel": "取消",
"common.loading": "載入中…",
"common.back": "返回",
"common.delete": "刪除",
"common.edit": "編輯",
"common.search": "搜尋",
"common.confirm": "確定",
"common.optional": "選填",
"common.success": "已儲存",
"common.error": "發生錯誤",
"common.yes": "是",
"common.no": "否",
2026-07-10 12:54:45 +00:00
// 後端 envelope codeapps/backend response + middleware
"api.err.unknown": "操作失敗,請稍後再試",
"api.err.network": "無法連線後端,請確認網路或服務是否啟動",
"api.err.400001": "請求格式不正確",
// 與後端 400003 / ValidatePasswordPolicy 同一句(勿各寫各的)
"api.err.400003": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
"password.policy.hint": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
"password.policy.minLen": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
"password.policy.needUpper": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
"password.policy.needLower": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
"password.policy.needDigit": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
"password.policy.needSymbol": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
"api.err.400004": "驗證碼無效或已過期",
"api.err.400020": "不能停權自己的帳號",
"api.err.400021": "不能移除或停權最後一位管理員",
"api.err.401001": "請先登入",
"api.err.401002": "登入已失效,請重新登入",
"api.err.401003": "找不到會員資料,請重新登入",
"api.err.401010": "Email 或密碼錯誤",
"api.err.403001": "帳號已停權",
"api.err.403002": "需要管理員權限",
"api.err.404001": "找不到資料",
"api.err.404002": "查無此信箱,請確認後再試",
"api.err.409001": "此 Email 已被註冊",
"api.err.500000": "伺服器發生錯誤,請稍後再試",
"api.err.501000": "此功能尚未實作",
// 後端 data.message 成功文案
"api.ok.verifySent": "驗證碼已寄出,請查收信箱",
"api.ok.verifyIssued": "驗證碼已產生",
"api.ok.resetSent": "重設信已寄出,請查收信箱",
"api.ok.passwordUpdated": "密碼已更新",
"api.ok.loggedOut": "已登出",
"api.ok.unbound": "已解除綁定",
2026-07-10 05:10:31 +00:00
"topbar.notifications": "通知",
"topbar.unread": "{n} 未讀",
"topbar.markAllRead": "全已讀",
"topbar.noNotifications": "目前沒有通知",
"topbar.jobsCenter": "任務中心",
"topbar.moreOlder": "還有 {n} 則較舊",
"topbar.account": "帳號選單",
"role.admin": "管理員",
"role.member": "一般會員",
"role.verified": "已驗證",
"role.unverified": "未驗證",
"login.title": "登入巡樓",
"login.email": "Email",
"login.password": "密碼",
"login.submit": "登入",
"login.submitting": "登入中…",
"login.forgot": "忘記密碼?",
"login.mockHint": "管理員 demo@harbor.local / demo · 一般會員 alice@harbor.local / alice",
2026-07-10 12:54:45 +00:00
"login.liveHint": "Live 後端admin@haixun.local / admin123gateway :8888",
2026-07-10 05:10:31 +00:00
"forgot.title": "忘記密碼",
"forgot.submit": "寄送重設連結",
"forgot.submitting": "送出中…",
"forgot.back": "返回登入",
2026-07-10 12:54:45 +00:00
"forgot.hint": "輸入註冊用 Email我們會寄送重設連結與驗證碼。",
2026-07-10 05:10:31 +00:00
"forgot.mockMail": "重設信",
2026-07-10 12:54:45 +00:00
"forgot.openReset": "前往輸入驗證碼/重設密碼",
2026-07-10 05:10:31 +00:00
"forgot.retry": "再試一次",
2026-07-10 12:54:45 +00:00
"forgot.nextStep": "請查收信箱中的驗證碼或連結,再到重設頁完成新密碼。",
2026-07-10 05:10:31 +00:00
"reset.title": "設定新密碼",
2026-07-10 12:54:45 +00:00
"reset.hint": "請輸入信箱、驗證碼(信內 6 碼或連結參數)與新密碼。",
"reset.code": "驗證碼",
"reset.codePh": "信內 6 位數字",
"reset.needEmail": "請輸入 Email",
"reset.needCode": "請輸入驗證碼",
2026-07-10 05:10:31 +00:00
"reset.newPassword": "新密碼",
"reset.confirm": "確認新密碼",
"reset.submit": "更新密碼",
"reset.submitting": "更新中…",
"reset.missingToken": "連結缺少 token。請從「忘記密碼」重新申請。",
"verify.title": "驗證信箱",
"verify.pending": "尚未驗證",
"verify.body": "帳號已開通登入,但信箱未驗證前無法使用功能。請輸入寄到你信箱的 6 位驗證碼。",
"verify.code": "驗證碼",
"verify.submit": "完成驗證",
"verify.submitting": "驗證中…",
"verify.resend": "重新寄送驗證碼",
"verify.sending": "寄送中…",
"verify.logout": "登出",
"verify.mockMail": "驗證信",
"verify.mockHint": "請輸入驗證碼:",
"verify.after": "驗證完成後即可使用今日、創作、海巡等功能。",
"settings.title": "設定",
"settings.localeCurrency": "語言與幣別",
"settings.locale": "介面語言",
"settings.currency": "顯示幣別",
"settings.currencyHint": "",
"settings.localeSaved": "語言與幣別已更新",
"settings.appearance": "外觀",
"settings.theme": "主題",
"settings.themeLight": "淺色",
"settings.themeDark": "深色",
"settings.themeSystem": "跟隨系統",
"settings.themeHint": "",
"settings.themeSaved": "主題已更新",
"settings.themeToLight": "切換成淺色",
"settings.themeToDark": "切換成深色",
"settings.dataSource": "資料來源",
2026-07-10 12:54:45 +00:00
"settings.dataSourceHint":
"mock = 瀏覽器本機假資料live = 打 apps/backend gateway。切 live 後請重新登入。",
"settings.dataSourceMock": "Mock本機",
"settings.dataSourceLive": "Live後端 API",
"settings.dataSourceCurrent": "目前",
"settings.dataSourceSwitchedLive": "已切到 Live — 請用後端帳號重新登入admin@haixun.local / admin123",
"settings.dataSourceSwitchedMock": "已切回 Mock",
"settings.dataSourceLiveNeedGateway": "需 gateway 在 :8888或 Vite proxy /api",
2026-07-10 05:10:31 +00:00
"settings.ai": "AI",
"settings.search": "搜尋",
"settings.member": "會員與登入",
"settings.usageCard": "AI搜尋額度",
"settings.usageCardHint": "",
"settings.viewUsage": "查看用量",
"settings.editProfile": "編輯會員資料",
"settings.mockLogin": "demo@harbor.local / demo",
"settings.memberHint": "",
"usage.title": "用量與方案",
"usage.desc": "",
"usage.creditsUsed": "本月已用點數",
"usage.remaining": "剩餘 {n} 點",
"usage.percentUsed": "{n}% 已使用",
"usage.breakdown": "分項用量",
"usage.plans": "方案",
"usage.current": "目前",
"usage.inUse": "使用中",
"usage.switchMock": "切換方案",
"usage.perMonth": "點/月",
"usage.ledger": "最近使用紀錄",
"usage.emptyTitle": "本月還沒有扣點",
"usage.emptyDesc": "",
"usage.planNote": "",
"usage.switched": "已切換為 {name}",
"usage.meter.times": "{count} 次 · {credits} 點",
"usage.meter.cap": "單項參考上限 {count}/{cap} 次",
"usage.plan.free.blurb": "試用與個人輕量經營",
"usage.plan.starter.blurb": "小團隊日常發文與海巡",
"usage.plan.pro.blurb": "多帳、重度 AI 與研究",
"profile.title": "會員資料",
"profile.desc": "",
"profile.accountStatus": "帳號開通狀態",
"profile.basic": "基本資料",
"profile.avatar": "頭像",
"profile.avatarUpload": "上傳頭像",
"profile.avatarRemove": "移除頭像",
2026-07-10 12:54:45 +00:00
"profile.avatarHint": "JPGPNGWebP5MB 內。選圖後按「儲存基本資料」寫入;「移除頭像」會立刻清除。",
2026-07-10 05:10:31 +00:00
"profile.avatarSaved": "頭像已更新",
"profile.avatarCleared": "已移除頭像",
"profile.avatarFail": "無法讀取圖片",
"profile.displayName": "顯示名稱",
"profile.bio": "簡介(選填)",
"profile.timezone": "時區",
"profile.notifyEmail": "Email 通知",
"profile.password": "變更密碼(選填)",
"profile.currentPassword": "目前密碼",
"profile.newPassword": "新密碼",
"profile.confirmPassword": "確認新密碼",
"profile.emailVerified": "信箱已驗證",
"profile.emailUnverified": "信箱未驗證",
"profile.roleAdmin": "管理員",
"profile.roleMember": "一般會員",
"profile.loginEmail": "登入信箱:{email}",
"profile.verifiedAt": " · 驗證於 {time}",
"profile.goVerify": "去驗證信箱",
"profile.roleTags": "權限標籤:{labels}",
"profile.roleNote": "角色由系統指派;改信箱後需重新驗證。",
"profile.saveBasic": "儲存基本資料",
"profile.updatePassword": "更新密碼",
"profile.saved": "會員資料已儲存",
"profile.savedUnverified": "資料已儲存。信箱尚未驗證或已變更,請完成驗證後才能繼續使用功能。",
"profile.saveFail": "儲存失敗",
"profile.needNewPassword": "請輸入新密碼",
"profile.passwordMismatch": "兩次新密碼不一致",
"profile.needCurrentPassword": "請輸入目前密碼",
2026-07-10 12:54:45 +00:00
"profile.wrongCurrentPassword": "目前密碼不正確",
2026-07-10 05:10:31 +00:00
"profile.passwordUpdated": "密碼已更新",
"profile.passwordFail": "變更密碼失敗",
"profile.listJoin": "、",
"profile.tenantUid": " · tenant {tenant} · uid {uid}",
2026-07-10 12:54:45 +00:00
"profile.inviteBadge": "邀請碼",
"profile.inviteHint": "分享給朋友加入;日後活動可依邀請關係計算。",
"profile.gotoInvite": "查看邀請關係",
"invite.title": "邀請關係",
"invite.desc": "邀請碼與邀請關係;管理端為樹狀結構。",
"invite.tabs": "邀請檢視",
"invite.tab.mine": "我的邀請",
"invite.tab.tree": "關係樹",
"invite.myCode": "我的邀請碼",
"invite.codeLabel": "邀請碼",
"invite.copyCode": "複製",
"invite.copied": "已複製",
"invite.copyFail": "複製失敗",
"invite.stats": "直邀 {direct} · 延伸 {total}",
"invite.upline": "邀請人",
"invite.downlines": "直邀成員 · {n}",
"invite.noUpline": "無邀請人",
"invite.noDownline": "尚無直邀",
"invite.directN": "直邀 {n}",
"invite.claimHint": "若註冊時沒填,可在此補上邀請人的邀請碼(綁定後不可自行更改)。",
"invite.claimLabel": "邀請碼",
"invite.claimPh": "例如 HX-DEMO01",
"invite.claimSubmit": "確認綁定",
"invite.claimOk": "已綁定邀請人:{name}",
"invite.claimOkGeneric": "已綁定邀請人",
"invite.claimFail": "綁定失敗",
"invite.claimLocked": "已綁定,如需調整請聯絡管理員。",
"invite.loadFail": "載入失敗",
"invite.treeEmpty": "尚無資料",
"invite.treeSearch": "搜尋",
"invite.treeSearchPh": "名稱 / Email / 邀請碼",
"invite.treeCount": "{n} 人",
"invite.treeMatchCount": "命中 {n} · 共 {total}",
"invite.treeNoMatch": "沒有符合的島民",
"invite.treeNoMatchHint": "換個關鍵字試試",
"invite.clearSearch": "清除",
"invite.moveTitle": "調整歸屬",
"invite.newParent": "邀請人",
"invite.root": "(無 · 獨立)",
"invite.confirmMove": "確認",
"invite.moved": "已調整「{name}」→「{parent}」",
"invite.moveFail": "調整失敗",
"invite.openFromAdmin": "邀請關係",
"invite.parentField": "邀請人",
"invite.orgPickRoot": "選一個起點(含無人邀請、自己進來的)",
"invite.orgRoots": "起點",
"invite.orgPath": "路徑",
"invite.orgChainN": "延伸 {n}",
"invite.orgFocusStats": "直邀 {direct} · 延伸 {total}",
"invite.orgDirects": "直邀成員 · {n}",
"invite.orgNoDirects": "沒有直邀成員",
"invite.err.notFound": "找不到會員",
"invite.err.notLoggedIn": "尚未登入",
"invite.err.needAdmin": "需要管理員權限",
"invite.err.memberNotFound": "找不到島民",
"invite.err.selfParent": "不能把自己設為邀請人",
"invite.err.parentNotFound": "找不到指定的邀請人",
"invite.err.cycle": "不可掛到自己邀請鏈的下層(會形成環)",
"invite.err.repoMissing": "邀請資料層尚未載入,請重新整理頁面",
"invite.err.alreadyBound": "你已有邀請人,無法再補填",
"invite.err.codeRequired": "請輸入邀請碼",
"invite.err.codeNotFound": "找不到此邀請碼",
"invite.err.codeSelf": "不能填自己的邀請碼",
2026-07-10 05:10:31 +00:00
"admin.users.title": "島民管理",
"admin.users.desc": "",
"admin.users.needAdmin": "需要管理員權限",
"admin.users.list": "島民列表 · {n}",
"admin.users.detail": "島民詳情",
"admin.users.pick": "選擇島民",
"admin.users.search": "搜尋名稱 / uid",
"admin.users.searchPh": "島民名稱、Email 或 uid",
"admin.users.create": "新增島民",
"admin.users.suspend": "停權",
"admin.users.unsuspend": "復權",
"admin.users.suspended": "已停權",
"admin.users.active": "正常",
"crew.title": "帳號",
"crew.tab.accounts": "帳號",
"crew.tab.personas": "人設",
"crew.connect": "連接帳號",
"crew.connecting": "新增中…",
"crew.refreshAll": "全部刷新 session",
"crew.refreshing": "刷新中…",
"crew.empty": "尚無帳號",
"crew.unusable": "不可用",
"crew.expires": "過期 {time}",
"crew.lastRefresh": "上次更新 {time}",
"crew.refreshSession": "刷新 session",
"crew.session.ok": "session 有效",
"crew.session.soon": "即將到期",
"crew.session.expired": "session 過期",
"crew.session.unknown": "session 未知",
"crew.msg.refreshed": "@{user} session 已刷新(延長約 30 天)",
"crew.msg.refreshedAll": "已刷新 {n} 個帳號 session",
"crew.msg.refreshFail": "刷新失敗",
"crew.confirmDelete": "確定刪除帳號 @{user}\n刪除後無法再選為 lead / cast。",
"today.findTopic": "找話題",
"today.pendingReplies": "待回覆",
"today.pendingRepliesN": "待回覆 · {n}",
"today.newThread": "開新串",
"today.metricsAria": "今日數值",
"today.metric.pending": "待回",
"today.metric.pendingHint": "海巡佇列",
"today.metric.doneGoal": "已回/目標",
"today.metric.sentToday": "今日已發",
"today.metric.running": "進行中 {n}",
"today.metric.sentDone": "完成的發送",
"today.metric.failed": "發送異常",
"today.metric.needAction": "需處理",
"today.metric.ok": "正常",
"today.pending.title": "待回覆 · {n}",
"today.pending.empty": "目前沒有待回",
"today.goScout": "去海巡",
"today.pending.more": "還有 {n} 則 →",
"today.pending.handle": "海巡處理",
"today.pending.start": "開始處理",
"today.topics.title": "找話題",
"today.topics.empty": "還沒有話題",
"today.goStudio": "去創作",
"today.heat": "熱度 {n}",
"today.topicAngle": "可當開場角度",
"today.moreInspire": "更多靈感",
"today.useTopic": "用話題開串",
"today.outbox.title": "今日發送",
"today.outbox.empty": "還沒有今日發送。可先",
"today.outbox.emptyMid": ",完成後會出現在",
"today.outbox.emptyEnd": "。",
"today.outbox.summary": "已完成 {sent} · 進行中 {running} · 異常 {failed}",
"today.badge.failed": "失敗",
"today.badge.scheduling": "排程",
"today.badge.sending": "發送中",
"today.openOutbox": "開啟發送",
"today.accounts.title": "帳號成效",
"today.accounts.empty": "尚無成效",
"today.postsCount": "{n} 則貼文",
"today.views": "瀏覽",
"today.likes": "讚",
"today.repliesShort": "回",
"today.fullInsights": "完整成效 · 月比圖",
"today.viewPosts": "看已發文",
"today.manageAccounts": "管理帳號",
"outbox.title": "發送",
"outbox.tabsAria": "發送分頁",
"outbox.tab.active": "進行中",
"outbox.tab.history": "歷史",
"outbox.empty": "尚無發送",
"outbox.activeEmpty": "進行中是空的",
"outbox.historyEmpty": "尚無歷史",
"outbox.historyN": "歷史({n}",
"outbox.backActive": "回進行中({n}",
"outbox.progress": "進度 {progress}",
"outbox.detail": "詳情",
"outbox.deleting": "刪除中…",
"outbox.confirmDelete": "刪除發送項目「{title}」?\n無法復原。",
"outbox.deleted": "已刪除「{title}」",
"outbox.deleteFail": "刪除失敗",
"outbox.status.scheduling": "排程中",
"outbox.status.active": "發送中",
"outbox.status.completed": "已完成",
"outbox.status.partial_failed": "部分失敗",
"outbox.status.cancelled": "已取消",
"outbox.detail.missingId": "缺少 id",
"outbox.detail.notFound": "找不到發送",
"outbox.detail.markAllOk": "標記全部成功",
"outbox.detail.markRootFail": "標記主貼失敗",
"outbox.detail.processing": "處理中…",
"outbox.detail.delete": "刪除這筆",
"outbox.detail.back": "返回列表",
"outbox.detail.root": "主貼",
"outbox.detail.replyN": "回覆 {n}",
"outbox.detail.retry": "重試",
"outbox.detail.opFail": "操作失敗",
"studio.title": "創作",
"studio.account": "帳號",
"studio.persona": "人設",
"studio.personaReady": "人設 ready",
"studio.personaNotReady": "人設未就緒",
"studio.tab.posts": "我的貼文",
"studio.tab.mentions": "提及 @",
"studio.tab.compose": "寫一則",
"studio.tab.plays": "互回方案",
"studio.tab.inspire": "靈感",
"studio.tab.insights": "成效",
"mentions.hint": "誰 @ 你。待回 {n} 則。每則可改帳號/人設(預設用頂部)。",
"mentions.scoutLink": "海巡外展",
"mentions.empty": "尚無提及",
"mentions.status.pending": "待回",
"mentions.status.replied": "已回",
"mentions.status.skipped": "略過",
"mentions.reply": "回覆",
"mentions.skip": "略過",
"mentions.draftLabel": "回覆草稿",
"mentions.repliedPrefix": "已回:{text}",
"mentions.needPersona": "請選 ready 人設再 AI 產文",
"mentions.fail": "失敗",
"mentions.marked": "已標記回覆(帳號 @{user}",
"mentions.withImages": " · 附圖 {n}",
"compose.hint": "單篇發文(非串場)。互回請用",
"compose.hintEnd": "。",
"compose.playsLink": "串場",
"compose.personaOff": "人設未 ready仿寫分析等 AI 工具停用。",
"compose.title": "標題(選填)",
"compose.titlePh": "方便在 Outbox 辨識",
"compose.body": "正文",
"compose.bodyPh": "寫下這則貼文…",
"compose.tool.mimic": "仿寫",
"compose.tool.viral": "爆紅分析",
"compose.tool.research": "上網補資料",
"compose.tool.image": "產圖",
"compose.mimic.title": "仿寫別人貼文",
"compose.mimic.source": "參考全文",
"compose.mimic.sourcePh": "貼上想仿寫的貼文…",
"compose.mimic.running": "仿寫中…",
"compose.mimic.run": "依人設仿寫到正文",
"compose.mimic.done": "仿寫完成,可再改",
"compose.viral.title": "爆紅分析",
"compose.viral.hint": "分析參考文或目前正文的鉤子/結構/可複製點。",
"compose.viral.source": "分析對象(可空=用正文)",
"compose.viral.running": "分析中…",
"compose.viral.run": "開始分析",
"compose.viral.result": "分析結果",
"compose.viral.done": "爆紅分析完成",
"compose.viral.needText": "請貼參考文或先寫正文",
"compose.research.title": "上網補專業資料",
"compose.research.q": "關鍵字",
"compose.research.qPh": "例如:無香洗劑 敏感肌",
"compose.research.running": "搜尋中…",
"compose.research.insert": "插入勾選內容到正文",
"compose.research.inserted": "已插入 {n} 條補充",
"compose.image.title": "產圖",
"compose.image.prompt": "畫面描述",
"compose.image.promptPh": "可空=從正文摘要",
"compose.image.running": "產圖中…",
"compose.image.run": "產生圖片",
"compose.image.done": "已產圖",
2026-07-10 12:54:45 +00:00
"compose.scheduleAt": "預計發送時間",
"compose.scheduleHint": "到點後由 Outbox 依序送出;可選現在。",
"compose.scheduleNow": "設為現在",
2026-07-10 05:10:31 +00:00
"compose.publish": "送出到 Outbox",
"compose.publishing": "送出中…",
"compose.publishFail": "送出失敗",
"compose.fail": "失敗",
"compose.attachN": "附圖 {n}",
"compose.personaStatus": "人設:{status}",
"compose.ready": "ready",
"compose.notReady": "未就緒",
"posts.sync": "重新同步 Threads",
"posts.syncing": "同步中…",
"posts.syncedAt": "同步 {time}",
"posts.notSynced": "未同步",
"posts.syncDone": "已同步 Threads 成效(讚/回/轉發/引用/瀏覽/分享)",
"posts.empty": "尚無貼文",
"posts.openThreads": "開 Threads",
"posts.insight": "分析洞察:{text}",
"posts.review": "覆盤:{text}",
"posts.formulaResult": "結構分析結果",
"posts.collapseReplies": "收合留言",
"posts.repliesBtn": "留言({total})· 未回 {pending}",
"posts.replyRoot": "回主貼",
"posts.analyzing": "分析中…",
"posts.reanalyze": "重新分析結構",
"posts.analyze": "分析結構",
"posts.mimicThis": "仿寫這則",
"posts.rootDraft": "回主貼草稿",
"posts.filter.pending": "未回覆({n}",
"posts.filter.replied": "已回覆({n}",
"posts.filter.all": "全部({n}",
"posts.noPending": "沒有未回覆留言",
"posts.noReplied": "還沒有已回覆留言",
"posts.noReplies": "尚無留言",
"posts.status.pending": "未回覆",
"posts.status.replied": "已回覆",
"posts.likesN": "讚 {n}",
"posts.childCount": "{n} 則子留言",
"posts.mine": "我方",
"posts.replyThis": "回這則",
"posts.replyAgain": "再回一則",
"posts.replyTo": "回 @{user}",
"posts.replyAgainTo": "再回 @{user}",
"posts.needPersona": "請先選 ready 人設再 AI 產文",
"posts.genFail": "生成失敗",
"posts.needText": "請先產生或輸入回覆",
"posts.sent": "已用 @{user} 發送",
"posts.sentImages": "(附圖 {n}",
"posts.accountFallback": "帳號",
"posts.sendFail": "發送失敗",
"posts.analyzeDone": "結構分析完成(手動觸發)",
"posts.analyzeFail": "分析失敗",
"wizard.newTitle": "編互回劇本",
"wizard.editTitle": "編輯互回劇本",
"wizard.prev": "上一步",
"wizard.next": "下一步",
"wizard.err.topic": "請填主題",
"wizard.err.lead": "請選擇主帳號",
"wizard.err.leadUnusable": "主帳號不可用",
"wizard.submitFail": "提交失敗",
"wizard.unnamedPlay": "未命名串場",
"wizard.step.topic": "聊什麼",
"wizard.step.crew": "誰出場",
"wizard.step.script": "誰說什麼",
"wizard.step.preview": "預覽",
"wizard.step.schedule": "何時發",
"wizard.step.submit": "送出",
"wizard.stepperAria": "wizard 步驟",
"wizard.topic.title": "1. 這串要聊什麼",
"wizard.topic.name": "標題(可選)",
"wizard.topic.namePh": "例如:週末咖啡",
"wizard.topic.topic": "主題一句話",
"wizard.topic.topicPh": "這串文想聊什麼?",
"wizard.topic.aiView": "AI 視角",
"wizard.topic.personaNotReady": "人設未就緒",
"wizard.topic.generating": "生成中…",
"wizard.topic.aiSuggest": "AI 幫我想",
"wizard.topic.quickFill": "快速填入",
"wizard.topic.sampleTitle": "週末咖啡話題",
"wizard.topic.sampleTopic": "週末想找間不踩雷的咖啡店,插座要多、能坐久。",
"wizard.topic.aiTitle": "AI 主題",
"wizard.topic.personaOpen": "{name}開場",
"wizard.crew.title": "2. 出場",
"wizard.crew.lead": "主帳",
"wizard.crew.noUsable": "尚無可用帳號",
"wizard.crew.unusable": "不可用",
"wizard.crew.cast": "配角",
"wizard.script.title": "3. 台詞",
"wizard.script.persona": "人設",
"wizard.script.personaNotReady": "人設未就緒",
"wizard.script.root": "主貼",
"wizard.script.replyN": "回覆 {n}",
"wizard.script.generating": "生成中…",
"wizard.script.ai": "AI 產文",
"wizard.script.account": "帳號:{name}",
"wizard.script.noLead": "(未選 lead",
"wizard.script.speaker": "發言帳號",
"wizard.script.leadTag": "lead",
"wizard.script.text": "文案",
"wizard.script.rootPh": "主貼內容…",
"wizard.script.replyPh": "回覆內容…",
"wizard.script.addReply": "新增回覆步驟",
"wizard.preview.title": "4. 預覽這段對話",
"wizard.preview.unknown": "未知",
"wizard.preview.unknownAccount": "未知帳號",
"wizard.preview.root": "主貼",
"wizard.preview.leadTalk": "lead 接話",
"wizard.preview.empty": "(空白)",
"wizard.schedule.title": "5. 何時發出去",
"wizard.schedule.start": "第一則(主貼)時間",
"wizard.schedule.interval": "回覆間隔(分鐘)",
"wizard.schedule.intervalHint": "相對上一步",
"wizard.submit.title": "6. 送出排程",
"wizard.submit.body": "確認後會把「{title}」這串互回(共 {n} 步)送進 Outbox依序用各帳號發出。",
"wizard.submit.unnamed": "未命名",
"wizard.submit.root": "主貼",
"wizard.submit.replyN": "回覆 {n}",
"wizard.submit.submitting": "提交中…",
"wizard.submit.run": "提交到 Outbox",
"reply.account": "用哪個帳號回",
"reply.persona": "用人設",
"reply.notReady": "此人設未 ready無法 AI 產文(仍可手打後發送)。",
"reply.draft": "回覆草稿",
"reply.attach": "附圖",
"reply.generating": "生成中…",
"reply.ai": "AI 產文",
"reply.sending": "發送中…",
"reply.send": "發送",
"image.attach": "附圖",
"image.attachFail": "附圖失敗",
"image.attachedAria": "已附圖片",
"image.alt": "附圖",
"image.named": "附圖 {n}",
"image.remove": "移除圖片",
"image.full": "已滿 {max} 張",
"image.more": "再附圖({n}/{max}",
"metrics.aria": "貼文成效",
"metrics.like": "讚",
"metrics.reply": "回覆",
"metrics.repost": "轉發",
"metrics.quote": "引用",
"metrics.view": "瀏覽",
"metrics.share": "分享",
"metrics.type.quote": "引用貼",
"metrics.type.reply": "回覆貼",
"metrics.type.image": "圖片",
"metrics.type.video": "影片",
"metrics.type.carousel": "輪播",
"metrics.type.repost": "轉發",
"metrics.type.text": "文字",
"metrics.type.post": "貼文",
"jobs.title": "任務",
"jobs.startDemo": "啟動任務",
"jobs.empty": "尚無任務",
"jobs.total": "共 {n} 筆",
"jobs.showing": " · 顯示前 {n}",
"jobs.detail": "詳情",
"jobs.loadMore": "載入更多(還有 {n}",
"jobs.notFound": "找不到任務",
"jobs.progress": "進度 {n}%",
"jobs.updated": "更新 {time}",
"jobs.backList": "返回列表",
"plans.title": "變更方案",
"plans.current": "目前方案",
"plans.perMonth": "/月",
"plans.monthlyCredits": "每月 {n} 點",
"plans.usageLink": "用量",
"plans.inUse": "使用中",
"plans.recommended": "推薦",
"plans.creditsPerMonth": "每月 {n} 點",
"plan.cta.current": "目前方案",
"plan.cta.upgrade": "升級",
"plan.cta.downgrade": "降級",
"plan.cta.switch": "切換",
"plan.free.headline": "試用與個人輕量經營",
"plan.free.bullet1": "每月 {n} 點 AI搜尋",
"plan.free.bullet2": "完整功能:創作、海巡、發送",
"plan.free.bullet3": "適合先熟悉流程",
"plan.free.bullet4": "可隨時升級",
"plan.free.right1": "可使用完整功能:帳號、創作、海巡、發送、任務與靈感。",
"plan.free.right2": "每月固定點數,用在文案、研究、搜尋與生圖。",
"plan.free.right3": "達上限後需等下月或升級(除非管理員開不擋額度)。",
"plan.free.quota1": "每月配給 {n} 點。",
"plan.free.quota2": "參考:文案 {copy}、研究 {research}、搜尋 {search}、生圖 {image} 次。",
"plan.free.note1": "無需付款,確認即切換。",
"plan.free.note2": "正式金流後的發票規則另訂。",
"plan.starter.headline": "小團隊日常發文與海巡",
"plan.starter.bullet1": "每月 {n} 點(約 6× Free",
"plan.starter.bullet2": "穩定發文、回覆、海巡",
"plan.starter.bullet3": "適合 13 人節奏",
"plan.starter.bullet4": "付款成功立即生效",
"plan.starter.right1": "付款成功後本帳改為 Starter當月依新額度計算。",
"plan.starter.right2": "點數支撐固定發文、回覆草稿與定期海巡。",
"plan.starter.right3": "功能與 Free 相同,差在能用多久。",
"plan.starter.quota1": "每月 {n} 點 · {price}。",
"plan.starter.quota2": "參考:文案 {copy}、研究 {research}、搜尋 {search}、生圖 {image} 次。",
"plan.starter.note1": "需付款成功才變更方案。",
"plan.starter.note2": "自然月重置,未用完點數不累積至下月。",
"plan.pro.headline": "多帳、重度 AI 與研究",
"plan.pro.bullet1": "每月 {n} 點(約 4× Starter",
"plan.pro.bullet2": "高頻文案/研究/生圖",
"plan.pro.bullet3": "適合代理與多品牌",
"plan.pro.bullet4": "付款成功立即生效",
"plan.pro.right1": "付款成功後本帳改為 Pro當月依 Pro 額度計算。",
"plan.pro.right2": "適合多帳、大量回覆與深研究,減少中途額度見底。",
"plan.pro.right3": "功能相同;買的是容量與節奏。",
"plan.pro.quota1": "每月 {n} 點 · {price}。",
"plan.pro.quota2": "參考:文案 {copy}、研究 {research}、搜尋 {search}、生圖 {image} 次。",
"plan.pro.note1": "付款失敗不會改方案。",
"plan.pro.note2": "付款完成後可於帳務紀錄查詢收據。",
"checkout.title": "確認方案",
"checkout.pickFirst": "請先選擇方案。",
"checkout.viewPlans": "看方案",
"checkout.cardLast4Required": "請填卡號末四碼",
"checkout.cardNameRequired": "請填持卡人",
"checkout.fail": "無法完成",
"checkout.confirmFree": "確認切換至 Free",
"checkout.payAndAction": "{action}並付款 {price}",
"checkout.subscribe": "訂閱",
"checkout.perMonth": "/月",
"checkout.monthlyCredits": "每月 {n} 點",
"checkout.youGet": "你會得到",
"checkout.quota": "額度",
"checkout.notes": "注意",
"checkout.cardholder": "持卡人",
"checkout.cardLast4": "卡號末四碼",
"checkout.amountDue": "應付金額",
"checkout.billedMonthly": "{name} · 按月計費",
"checkout.already": "已是此方案",
"checkout.processing": "處理中…",
"checkout.currentPlan": "目前方案",
"checkout.pickOther": "改選其他方案",
"checkout.cancel": "取消",
"usage.widget.titleUsed": "{name} · 已用 {used}{cap} 點",
"usage.widget.titleUnlimited": "{name} · 不擋額度",
"usage.widget.ariaUsed": "已用 {used} 點,共 {cap} 點",
"usage.widget.dialog": "方案與用量",
"usage.widget.currentPlan": "目前方案",
"usage.widget.unlimited": "不擋額度",
"usage.widget.perMonth": "/月",
"usage.widget.monthUsage": "本月用量",
"usage.widget.remaining": "還剩 {n} 點",
"usage.widget.leftShort": "還剩 {n}",
"usage.widget.overShort": "已超額",
"usage.widget.upgradeShort": "升級",
"usage.widget.upgrade": "升級方案",
"usage.widget.includes": "這個方案包含",
"usage.widget.nudge": "本月額度快用完了,升級可立刻加大點數。",
"usage.widget.changePlan": "變更方案",
"usage.widget.usageDetail": "用量明細",
"usage.meter.ai_copy": "AI 文案",
"usage.meter.ai_research": "AI 研究",
"usage.meter.web_search": "搜尋",
"usage.meter.ai_image": "AI 生圖",
"usage.meter.barAria": "{label} {count} 次 {credits} 點,上限 {cap}",
"usage.ledger.costAria": "消耗 {n} 點",
"usage.chart.period": "區間",
"usage.chart.allocated": "配給",
"usage.chart.consumed": "消耗",
"usage.chart.pctTitle": "消耗佔配給比例",
"usage.chart.aria": "配給與消耗",
"usage.chart.colAria": "{label} 配給 {purchased} 消耗 {consumed}",
2026-07-10 12:54:45 +00:00
"settings.provider": "Provider",
"settings.model": "模型",
"settings.aiUnifiedHint": "文案、研究、延伸全部使用同一 provider 與模型。",
2026-07-10 05:10:31 +00:00
"settings.fetchModels": "取得模型",
"settings.fetchingModels": "讀取中…",
2026-07-10 12:54:45 +00:00
"settings.apiKey": "API Key",
2026-07-10 05:10:31 +00:00
"settings.configured": "已設定",
"settings.notConfigured": "未設定",
"settings.modelsLoaded": "已取得 {provider} 模型清單",
"settings.aiSaved": "AI 設定已儲存",
"settings.searchSaved": "搜尋設定已儲存",
2026-07-10 12:54:45 +00:00
"settings.searchProvider": "搜尋 Provider",
"settings.expand": "延伸策略",
"settings.exaKey": "Exa API Key",
"settings.devMode": "開發模式(爬蟲測試海巡)",
"settings.devModeHint": "開啟後測試海巡可走 Chrome 爬蟲;正式發文/留言仍走 API。請下載擴充以同步 Threads 登入態。",
"settings.ext.title": "Chrome 擴充套件",
"settings.ext.desc": "開發模式需安裝此擴充,才能從 Chrome 同步 Threads session 到巡樓。",
"settings.ext.step1": "下載並解壓縮 ZIP得到 haixun-threads-sync 資料夾",
"settings.ext.step2": "Chrome 開啟 chrome://extensions開啟「開發人員模式」",
"settings.ext.step3": "點「載入未封裝項目」,選擇解壓後的資料夾",
"settings.ext.step4": "在擴充選項填入此站網址,再重新整理巡樓頁",
"settings.ext.download": "下載擴充套件ZIP",
2026-07-10 05:10:31 +00:00
"forgot.fail": "送出失敗",
"forgot.mockHint": "正式環境會寄到信箱;此處直接給連結:",
2026-07-10 12:54:45 +00:00
"forgot.checkInbox": "請檢查信箱(含垃圾郵件)。",
2026-07-10 05:10:31 +00:00
"reset.mismatch": "兩次密碼不一致",
"reset.fail": "重設失敗",
"reset.cardTitle": "重設密碼",
"reset.redirecting": "即將前往登入頁…",
"reset.loginNow": "立即登入",
2026-07-10 12:54:45 +00:00
"reset.passwordPh": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
"reset.forgotLink": "重新申請重設",
2026-07-10 05:10:31 +00:00
"verify.sendFail": "寄送失敗",
"verify.fail": "驗證失敗",
"verify.success": "信箱已驗證,可以使用巡樓了。",
"verify.codePh": "6 位數字",
"verify.currentAccount": "目前帳號:{email}",
"login.brandTitle": "巡樓 · Lapras",
"common.listSep": "、",
"common.dash": "—",
"scout.title": "海巡",
"scout.today": "今日",
"scout.purposeValue": "痛點回覆",
"scout.purposeActivity": "活躍短回",
"scout.goal": "今日目標(則)",
"scout.progress": "進度 {done}/{goal}",
"scout.intent": "我想找/回應",
"scout.keyword": "關鍵字",
"scout.intentPh": "例:換季頭皮刺癢、真的無香、週末有插座",
"scout.keywordPh": "例:週末 咖啡 遠端",
"scout.productOptional": "產品(選填)",
"scout.noProduct": "不帶產品",
"scout.brandFallback": "品牌",
"scout.placement": "置入:{label}",
"scout.painPart": " · 痛點「{pain}」",
"scout.noProductsBefore": "尚無產品,可到",
"scout.noProductsAfter": "新增。",
"scout.start": "開始",
"scout.startMore": "再撈一批",
"scout.fetching": "撈取中…",
"scout.runs": "海巡批次",
"scout.runCount": "批次({n}",
"scout.runSelectAria": "切換海巡批次",
"scout.runPending": "待回 {n} · ",
"scout.runDone": "已清完 · ",
"scout.runTotal": "{n} 則)",
"scout.deleteRun": "刪除這一批",
"scout.deleting": "刪除中…",
"scout.now": "現在這一則",
"scout.emptyBatch": "這一批沒有待回",
"scout.draft": "回覆草稿",
"scout.draftPhActivity": "短回…",
"scout.draftPhValue": "共感 → 建議…",
"scout.sendAccount": "用哪個帳號送",
"scout.noAccount": "無可用帳號",
"scout.personaForRegen": "人設(再產用)",
"scout.notReady": "(未就緒)",
"scout.skip": "略過",
"scout.regen": "再產",
"scout.send": "發送",
"scout.sending": "發送中…",
"scout.needAccountBefore": "請先到",
"scout.needAccountAfter": "連線可用帳號。",
"scout.knowledge": "周邊知識",
"scout.knowledgeWithLabel": "周邊知識 · {label}",
"scout.knowledgeLearn": "周邊知識 · 可學",
"scout.collapseKnowledge": "收合知識",
"scout.expandLearn": "展開學習 · {n} 則",
"scout.expandKnowledge": "展開知識",
"scout.deleteKnowledgeRun": "刪除此批知識與命中",
"scout.loadingKnowledge": "正在整理周邊知識…",
"scout.notesCount": "{n} 則",
"scout.noKnowledge": "尚無周邊知識",
"scout.product": "產品",
"scout.painsSolved": "能解的痛",
"scout.focus": "焦點",
"scout.all": "全部",
"scout.noWebSummary": "尚無網頁摘要",
"scout.queue": "佇列 · {n}",
"scout.collapseQueue": "收合佇列",
"scout.expandQueue": "展開佇列",
"scout.noOtherPending": "沒有其他待回",
"scout.learnPoints": "學習重點",
"scout.replyHooks": "回帖可借",
"scout.badgeCore": "最貼主題",
"scout.unnamedRun": "未命名批次",
"scout.thisRun": "此批次",
"scout.confirmDeleteRun": "刪除海巡批次「{label}」?\\n會一併刪除這批命中與周邊知識無法復原。",
"scout.deletedRun": "已刪除批次「{label}」",
"scout.deleteRunFail": "刪除批次失敗",
"scout.needKeyword": "先填關鍵字",
"scout.needIntent": "先寫這次要找什麼",
"scout.productMissing": "所選產品不在列表中,請重新選擇",
"scout.defaultLabel": "海巡",
"scout.newRunActivity": "新批次「{label}」· {n} 則待回",
"scout.newRunValue": "新批次「{label}」· {n} 則 · 請處理「現在這一則」",
"scout.knowledgeReady": "「{label}」周邊知識已備好 · {n} 則可學",
"scout.patrolFail": "這輪海巡失敗",
"scout.draftFail": "產草稿失敗",
"scout.skipped": "已略過",
"scout.noDraft": "沒有可發送的草稿",
"scout.accountFallback": "帳號",
"scout.sent": "已發送(@{who})· 今日 {done}/{goal}",
"scout.sendFail": "發送失敗",
"scout.confirmDeletePost": "刪除這則命中?",
"scout.stanceActivity": "短回 · 養活躍",
"scout.stanceProduct": "共感 · 可輕帶產品",
"scout.stanceRelation": "接話 · 建關係",
"scout.tier.core": "最貼主題",
"scout.tier.coreHint": "直接對準痛點/關鍵語,優先讀",
"scout.tier.adjacent": "相關周邊",
"scout.tier.adjacentHint": "鄰近情境,擴搜尋面",
"scout.tier.broad": "最廣泛",
"scout.tier.broadHint": "背景與對照,選讀即可",
"scout.relation.solves_pain": "對準痛點",
"scout.relation.nearby_scene": "鄰近場景",
"scout.relation.myth": "迷思澄清",
"scout.relation.contrast": "對照選購",
"scout.relation.background": "背景脈絡",
"brands.title": "品牌",
"brands.railAria": "品牌列表",
"brands.railLabel": "你的牌子",
"brands.add": "新增",
"brands.brandName": "品牌名稱",
"brands.brandNamePh": "例如:自家品牌",
"brands.creating": "建立中…",
"brands.createBrand": "建立品牌",
"brands.searchAria": "搜尋品牌",
"brands.searchPh": "搜尋品牌…",
"brands.empty": "尚無品牌",
"brands.noMatch": "無符合",
"brands.selectAria": "選擇品牌",
"brands.pickOne": "選一個品牌",
"brands.inUseHint": "使用中 · 海巡與創作會套用此牌",
"brands.inUse": "使用中",
"brands.tabInfo": "牌子資料",
"brands.tabProducts": "產品",
"brands.tabProductsN": "產品({n}",
"brands.displayName": "名稱",
"brands.brief": "摘要",
"brands.briefPh": "一句話說明這個牌子",
"brands.audience": "受眾",
"brands.audiencePh": "誰會在意、為什麼",
"brands.goals": "目標",
"brands.goalsPh": "想在 Threads 達成什麼",
"brands.saving": "儲存中…",
"brands.deleteBrand": "刪除品牌",
"brands.searchProductAria": "搜尋產品",
"brands.searchProductPh": "搜尋產品…",
"brands.addProduct": "新增產品",
"brands.noProducts": "尚無產品",
"brands.hasLink": "有連結",
"brands.painLabel": "痛點 ",
"brands.editProduct": "編輯產品",
"brands.newProduct": "新增產品",
"brands.importFromUrl": "從商品連結帶入",
"brands.fetching": "抓取中…",
"brands.fetch": "抓取",
"brands.pains": "痛點",
"brands.painsPh": "一列一個",
"brands.tags": "標籤",
"brands.tagsPh": "逗號分隔",
"brands.intro": "介紹",
"brands.link": "連結",
"brands.update": "更新",
"brands.createItem": "新增",
"brands.needName": "請輸入名稱",
"brands.created": "已建立「{name}」",
"brands.createFail": "建立失敗",
"brands.saved": "已儲存",
"brands.saveFail": "儲存失敗",
"brands.confirmDelete": "確定刪除「{name}」?",
"brands.deleted": "已刪除",
"brands.deleteFail": "刪除失敗",
"brands.fetchFail": "抓取失敗",
"brands.needLabelContext": "名稱與介紹為必填",
"brands.productUpdated": "已更新",
"brands.productAdded": "已新增",
"brands.confirmDeleteProduct": "刪除此產品?",
"insights.title": "帳號成效",
"insights.account": "帳號",
"insights.noAccount": "尚無帳號",
"insights.syncing": "同步中…",
"insights.syncPosts": "同步貼文",
"insights.myPosts": "我的貼文",
"insights.pickAccount": "選擇帳號",
"insights.goAccounts": "帳號",
"insights.kpiMonth": "本月指標",
"insights.monthViews": "本月瀏覽",
"insights.monthLikes": "本月讚",
"insights.monthReplies": "本月回覆",
"insights.engRate": "互動率",
"insights.vsPrev": "vs 上月",
"insights.avgNear": "近帖均 {rate}",
"insights.trendTitle": "趨勢與分析 · @{user}",
"insights.metricViews": "瀏覽",
"insights.metricLikes": "讚",
"insights.metricReplies": "回覆",
"insights.metricPosts": "貼文",
"insights.metricPostsFull": "貼文數",
"insights.chartMetrics": "圖表指標",
"insights.barsAria": "近月{metric},點柱查看該月分析",
"insights.barsLabel": "{metric} · 近 {n} 個月",
"insights.clickBar": " · 點柱看分析",
"insights.pickMonthAria": "選擇月份",
"insights.barTitle": "{label}{value}{est} · 點看分析",
"insights.est": "(估)",
"insights.monthSuffix": "{m}月",
"insights.sparkAria": "趨勢折線,點節點可選月",
"insights.analysisOf": "{label} 分析",
"insights.producedAt": "產出於 {time}",
"insights.hasEstimate": " · 含估測數據",
"insights.viewsVsPrev": " · 瀏覽 vs 前月 {delta}",
"insights.statPosts": "貼文",
"insights.statViews": "瀏覽",
"insights.statLikes": "讚",
"insights.statReplies": "回",
"insights.conclusions": "結論",
"insights.recommendations": "建議",
"insights.highlights": "當月亮點",
"insights.findTopics": "找話題",
"insights.goScout": "去探查",
"insights.selectMonth": "選擇月份",
"insights.topPosts": "表現較佳貼文",
"insights.noPosts": "尚無貼文",
"insights.postStats": "瀏覽 {views} · 讚 {likes} · 回 {replies}",
"insights.openThreads": "開啟 Threads",
"insights.zeroPct": "0%",
"plays.tabOwn": "我的貼文",
"plays.tabLink": "Threads 連結",
"plays.noPosts": "尚無貼文",
"plays.targetPost": "目標貼文",
"plays.likesSuffix": " (讚{n}",
"plays.linkCard": "貼 Threads 連結",
"plays.postLink": "貼文連結",
"plays.resolving": "解析中…",
"plays.resolve": "解析連結",
"plays.resolveHint": "解析後可排自家帳號在該則下面回覆。",
"plays.targetOwn": "目標貼文(自己的)",
"plays.openThreads": "開 Threads",
"plays.external": "外站貼",
"plays.addScheme": "新增方案",
"plays.schemeCount": "此目標目前 {n} 個方案",
"plays.noSchemes": "尚無方案",
"plays.replyCount": "{n} 則留言",
"plays.editTitle": "編輯:{title}",
"plays.schemeName": "方案名稱",
"plays.schemeNamePh": "例如:方案 A · 溫和接話",
"plays.speakersOwn": "可出場帳號(貼主帳固定可回)",
"plays.speakers": "可出場帳號",
"plays.postOwner": "(貼文主帳)",
"plays.noAccounts": "沒有可用帳號,請先到設定連線 Threads。",
"plays.interval": "間隔(分)",
"plays.applyInterval": "套用間隔",
"plays.aiEmpty": "空白則 AI",
"plays.aiBusy": "產文中…",
"plays.replies": "留言({n}",
"plays.stepN": "第 {n} 則",
"plays.who": "誰留",
"plays.personaOpt": "人設(選填)",
"plays.brandOpt": "品牌(選填)",
"plays.reply": "留言",
"plays.attach": "附圖",
"plays.addOne": "加一則",
"plays.saving": "儲存中…",
"plays.saveScheme": "儲存方案",
"plays.submitting": "送出中…",
"plays.submitOutbox": "送出到 Outbox",
"plays.closeEdit": "關閉編輯",
"plays.noTarget": "還沒有目標貼文",
"plays.resolved": "已解析連結",
"plays.resolveFail": "解析失敗",
"plays.filled": "已產 {n} 則",
"plays.needTarget": "請先選定目標貼文",
"plays.saved": "方案已儲存",
"plays.saveFail": "儲存失敗",
"plays.submitted": "已送進 Outbox",
"plays.submitFail": "送出失敗",
"plays.confirmDelete": "刪除此方案?",
"plays.accountFallback": "帳號",
"inspire.loading": "載入中…",
"inspire.trendsAria": "最近 Threads 夯什麼",
"inspire.trendsLabel": "最近 Threads 夯",
"inspire.refresh": "刷新",
"inspire.clearChat": "清空對話",
"inspire.pinAsElement": "套用為元素",
"inspire.you": "你",
"inspire.ai": "AI",
"inspire.system": "系統",
"inspire.useDraft": "用這則寫",
"inspire.openPlay": "開串場",
"inspire.generating": "產文中…",
"inspire.thinking": "思考中…",
"inspire.pinnedAria": "本輪已套用",
"inspire.pinned": "已套用",
"inspire.pickRight": "右側點選元素",
"inspire.unpinTitle": "點擊取消套用",
"inspire.inputAria": "跟 AI 說",
"inspire.inputPh": "想寫什麼?或改短一點、更口語…",
"inspire.send": "送出",
"inspire.generate": "產文",
"inspire.library": "元素庫",
"inspire.addNew": "+ 新增",
"inspire.kind": "類型",
"inspire.kindRole": "角色指令",
"inspire.kindSnippet": "片段",
"inspire.kindTrendNote": "熱點備註",
"inspire.kindBrand": "品牌",
"inspire.kindTrend": "熱點",
"inspire.name": "名稱",
"inspire.namePh": "例如:專業 Threads 寫手",
"inspire.body": "內容(會進 prompt",
"inspire.bodyPh": "你是一位…",
"inspire.saveElement": "存進元素庫",
"inspire.citeBrand": "引用品牌",
"inspire.applied": "已套用",
"inspire.clickApply": "點擊套用",
"inspire.noBrands": "尚無品牌",
"inspire.appliedToggle": "已套用 · 再點取消",
"inspire.deleteAria": "刪除",
"inspire.needInput": "先輸入一句,或直接產文",
"inspire.fail": "失敗",
"inspire.wantWrite": "想寫關於 {label}{summary}",
"inspire.trendBody": "主題:{label}。{summary}",
"inspire.pinnedTrend": "已套用熱點 {label}",
"inspire.needTitleBody": "請填名稱與內容",
"inspire.added": "已加入元素庫",
"inspire.addFail": "新增失敗",
"inspire.confirmRemove": "從元素庫移除此項?",
"inspire.confirmClear": "清空對話?(元素庫保留)",
"inspire.genMessage": "請依已套用元素寫一則 Threads",
"persona.add": "新增人設",
"persona.empty": "尚無人設",
"persona.emptyDesc": "新增後做分析即可用於產文。",
"persona.statusReady": "ready",
"persona.statusAnalyzing": "分析中",
"persona.statusPending": "待分析",
"persona.default": "預設",
"persona.backList": "← 人設列表",
"persona.tabOverview": "概要",
"persona.tabAnalyze": "分析",
"persona.tabFingerprint": "指紋",
"persona.tabPreview": "試產",
"persona.name": "名稱",
"persona.brief": "定位 brief",
"persona.briefPh": "是誰、對誰說、核心訊息…",
"persona.avoid": "護欄 · 禁止詞(逗號分隔)",
"persona.guardChars": "{n} 字",
"persona.banAi": " · 禁 AI 腔",
"persona.notReadySuffix": " · 未就緒",
"persona.setDefault": "設為預設",
"persona.modeAccount": "公開帳號",
"persona.modeText": "貼文字",
"persona.username": "Threads username",
"persona.fromBound": "從已綁帳號帶入",
"persona.select": "選擇…",
"persona.crawlAnalyze": "爬公開貼文並分析",
"persona.crawlBusy": "爬取/分析中…",
"persona.refText": "參考文字(--- 分隔多篇)",
"persona.refTextPh": "第一段…\n\n---\n\n第二段…",
"persona.sourceLabel": "來源說明(選填)",
"persona.sourcePh": "自己的舊文",
"persona.analyzeText": "從文字分析",
"persona.analyzeBusy": "分析中…",
"persona.sampleMeta": "樣本 {n}",
"persona.sourceManual": "貼文",
"persona.analyzeHint": "完成分析後會顯示 8D 摘要。",
"persona.fingerprintHint": "產文主體。可改口頭禪、節奏、禁忌;儲存後 Studio回覆會吃這份。",
"persona.fingerprint": "語言指紋",
"persona.fingerprintPh": "分析後自動填入…",
"persona.saveFingerprint": "儲存指紋",
"persona.tryGen": "試產主貼 + 回覆",
"persona.notReadyMsg": "人設未就緒",
"persona.rootPost": "主貼",
"persona.reply": "回覆",
"persona.hidePrompt": "隱藏 prompt block",
"persona.showPrompt": "顯示注入的 prompt",
"persona.promptBlock": "prompt blockpost",
"persona.pickOne": "選一個人設",
"persona.pickDesc": "或按新增開始分析。",
"persona.created": "已建立,請到「分析」完成帳號爬取或貼文字",
"persona.saved": "已儲存",
"persona.textDone": "文字分析完成 · {n} 段 → ready",
"persona.analyzeFail": "分析失敗",
"persona.reading": "正在讀取公開貼文…",
"persona.accountDone": "@{user} · {n} 則 → ready",
"persona.setDefaultMsg": "「{name}」已設為預設",
"persona.confirmDelete": "確定刪除人設「{name}」?",
"persona.deleted": "人設已刪除",
"persona.needReady": "請先完成分析ready",
"persona.dim.d1Tone": "D1 語氣人格",
"persona.dim.d2Structure": "D2 結構模板",
"persona.dim.d3Interaction": "D3 互動方式",
"persona.dim.d4Topics": "D4 主題分布",
"persona.dim.d5Rhythm": "D5 發文節奏",
"persona.dim.d6Visual": "D6 視覺語法",
"persona.dim.d7Conversion": "D7 轉換方式",
"persona.dim.d8Risk": "D8 風險紅線",
"admin.users.loadFail": "載入失敗",
"admin.users.created": "已新增島民「{name}」· 請複製下方密碼",
"admin.users.createFail": "新增失敗",
"admin.users.unlimitedOn": "「{name}」已設不擋額度(用量仍計算)",
"admin.users.unlimitedOff": "「{name}」已改回依方案擋額度",
"admin.users.updateFail": "更新失敗",
"admin.users.planSet": "「{name}」方案 → {plan}",
"admin.users.confirmSuspend": "確定停權「{name}」?\\n停權後無法登入。",
"admin.users.confirmUnsuspend": "確定復權「{name}」?\\n復權後可重新登入。",
"admin.users.didSuspend": "已停權「{name}」",
"admin.users.didUnsuspend": "已復權「{name}」",
"admin.users.suspendFail": "停權失敗",
"admin.users.unsuspendFail": "復權失敗",
"admin.users.markedVerified": "已將 {name} 標為信箱已驗證",
"admin.users.markedUnverified": "已將 {name} 標為未驗證",
"admin.users.rolesUpdated": "已更新 {name} 的權限:{roles}",
"admin.users.rolesFail": "權限更新失敗",
"admin.users.confirmReset": "確定幫「{name}」重設密碼?\\n臨時密碼會固定顯示直到你按關閉可重整。",
"admin.users.resetDone": "已重設 {name} 的密碼(下方可持續顯示,請複製後再關閉)",
"admin.users.resetFail": "重設失敗",
"admin.users.copied": "已複製到剪貼簿",
"admin.users.copyFail": "複製失敗,請手動選取密碼",
"admin.users.confirmDismissTemp": "關閉後此頁將不再顯示這組臨時密碼(若尚未複製請先複製)。確定關閉?",
"admin.users.tempPwNew": "新島民臨時密碼",
"admin.users.tempPw": "臨時密碼",
"admin.users.tempPwPersist": "(持續顯示 · 可重整)",
"admin.users.copyPw": "複製密碼",
"admin.users.close": "關閉",
"admin.users.createTitle": "新增島民",
"admin.users.memberName": "島民名稱",
"admin.users.displayNamePh": "顯示名稱",
"admin.users.email": "Email",
"admin.users.initPassword": "初始密碼(選填)",
2026-07-10 12:54:45 +00:00
"admin.users.initPasswordPh": "空白則自動產生;若填寫須符合密碼政策",
2026-07-10 05:10:31 +00:00
"admin.users.markVerifiedCheck": "信箱標為已驗證(可直接使用)",
"admin.users.alsoAdmin": "同時設為管理員",
"admin.users.creating": "建立中…",
"admin.users.createSubmit": "建立島民",
"admin.users.clear": "清除",
"admin.users.searchActive": "搜尋「{query}」· 可匹配名稱、Email、uid",
"admin.users.noMatch": "無符合",
"admin.users.none": "尚無島民",
"admin.users.you": "這是你",
"admin.users.status": "狀態",
"admin.users.role": "角色",
"admin.users.emailVerify": "信箱驗證",
"admin.users.bio": "簡介",
"admin.users.timezone": "時區",
"admin.users.notifyEmail": "Email 通知",
"admin.users.on": "開",
"admin.users.off": "關",
"admin.users.createdAt": "建立",
"admin.users.updatedAt": "更新",
"admin.users.accountStatus": "帳號狀態",
"admin.users.updating": "更新中…",
"admin.users.usageTitle": "用量與方案",
2026-07-10 12:54:45 +00:00
"admin.users.usageLiveSkip": "方案/額度屬 Usage 域live 後端尚未接上M3此區僅 mock 可改。",
2026-07-10 05:10:31 +00:00
"admin.users.plan": "方案",
"admin.users.planOption": "{name}{credits} 點/月)",
"admin.users.unlimited": "不擋額度",
"admin.users.byPlan": "依方案",
"admin.users.setUnlimited": "設為不擋額度",
"admin.users.setLimited": "改回擋額度",
"admin.users.unlimitedHint": "不擋額度達方案上限仍可繼續用AISearch 次數與點數照樣計算。",
"admin.users.loadingUsage": "載入用量設定…",
"admin.users.assignRoles": "指派權限",
"admin.users.memberBase": "{role}(基底,不可關閉)",
"admin.users.adminDesc": "{role} — 可管理島民與系統",
"admin.users.saving": "儲存中…",
"admin.users.saveRoles": "儲存權限",
"admin.users.markUnverifiedBtn": "標為未驗證",
"admin.users.markVerifiedBtn": "標為已驗證",
"admin.users.resetting": "重設中…",
"admin.users.resetTemp": "重設密碼(產生臨時)",
"admin.users.customPw": "或指定新密碼(選填)",
2026-07-10 12:54:45 +00:00
"admin.users.customPwPh": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
2026-07-10 05:10:31 +00:00
"admin.users.resetWithCustom": "用指定密碼重設",
"usage.tabMine": "我的用量",
"usage.tabTenant": "全體用量",
"usage.currentPlan": "目前方案",
"usage.planMeta": "/月 · 每月 {n} 點額度",
"usage.changePlan": "變更方案",
"usage.usedThisMonth": "本月已用",
"usage.remainLabel": "剩餘",
"usage.ledgerToggle": "使用紀錄",
"usage.collapse": "收合",
"usage.eventsCount": "{n} 筆",
"usage.granularity": "粒度",
"usage.day": "日",
"usage.monthUnit": "月",
"usage.year": "年",
"usage.from": "起",
"usage.to": "迄",
"usage.callCounts": "呼叫次數",
"usage.noMembers": "尚無會員",
"usage.planAria": "{name} 方案",
"usage.unlimitedTitle": "不擋額度",
"usage.setLimited": "改回擋額度",
"usage.setUnlimited": "設為不擋額度",
"usage.limitShort": "擋",
"usage.subscribed": "已訂閱 {name}",
"usage.unlimitedSet": "已設不擋額度",
"usage.limitedSet": "已改回擋額度",
"usage.planUpdated": "已更新方案 {name}",
"usage.fail": "失敗",
"currency.TWD": "新台幣 (TWD)",
"currency.USD": "美元 (USD)",
"currency.JPY": "日圓 (JPY)",
"currency.EUR": "歐元 (EUR)",
"currency.HKD": "港幣 (HKD)",
"locale.zh-TW": "繁體中文",
"locale.en": "English",
"pager.nav": "分頁",
"pager.pageSize": "每頁筆數",
"pager.perPage": "{n}/頁",
"pager.prev": "上一頁",
"pager.next": "下一頁",
"plays.defaultTitle": "新方案",
"plays.topicOnPost": "掛在:{snippet}",
"plays.topicOnExternal": "掛在:{label} · {snippet}",
"plays.externalFallback": "外站貼",
"persona.newName": "新人設",
"persona.previewTopic": "週末想找能坐久的咖啡店",
"persona.previewReplySample": "大安那間還行但人很多",
"inspire.playTitle": "靈感串場",
"wizard.topic.fallbackTopic": "生活小題",
"play.err.needLead": "請選擇主帳號",
"play.err.needRoot": "請至少有一則主貼",
"play.err.firstMustRoot": "第一則必須是主貼",
"play.err.rootMustLead": "主貼必須使用主帳",
"play.err.rootEmpty": "主貼文案不可空白",
"play.err.replyAccount": "回覆只能用主帳或已選配角",
"play.err.replyEmpty": "回覆文案不可空白",
"play.err.needTarget": "請選擇自己的貼文,或貼上 Threads 連結",
"play.err.needReplies": "請至少排 1 則留言",
"play.err.needReplyAccounts": "請至少選一個可回覆帳號",
"play.err.stepAccount": "每則留言都要指定可用帳號",
"play.err.stepEmpty": "留言內容不可空白",
"play.err.notFound": "找不到互回方案",
"time.justNow": "剛剛",
"time.minAgo": "{n} 分前",
"time.hourAgo": "{n} 小時前",
"time.dayAgo": "{n} 天前",
"time.min": "{n} 分鐘",
"time.hour": "{n} 小時",
"time.day": "{n} 天",
"time.expired": "已過期 {span}",
"time.remaining": "剩餘 {span}",
"time.sessionUnknown": "Session 未記錄",
"time.sessionExpired": "Session 已過期 · {absolute}",
"time.sessionSoon": "Session 即將到期 · {relative}{absolute}",
"time.sessionOk": "Session 有效 · {relative}{absolute}",
};
export const en: MessageDict = {
"app.name": "Lapras",
"app.nameEn": "Lapras",
"app.nameZh": "巡樓",
"app.tagline": "Patrol Threads with ease",
"app.taglineEn": "Patrol Threads with ease",
"nav.today": "Today",
"nav.crew": "Accounts",
"nav.studio": "Studio",
"nav.scout": "Patrol",
"nav.outbox": "Outbox",
"nav.jobs": "Jobs",
"nav.brands": "Brands",
"nav.more": "More",
"nav.moreTitle": "More",
"nav.users": "Islanders",
"nav.usage": "Usage & plans",
"nav.profile": "Profile",
2026-07-10 12:54:45 +00:00
"nav.invite": "Invites",
2026-07-10 05:10:31 +00:00
"nav.settings": "Settings",
"nav.logout": "Log out",
"nav.navigate": "Navigate",
"common.save": "Save",
"common.cancel": "Cancel",
"common.loading": "Loading…",
"common.back": "Back",
"common.delete": "Delete",
"common.edit": "Edit",
"common.search": "Search",
"common.confirm": "Confirm",
"common.optional": "Optional",
"common.success": "Saved",
"common.error": "Something went wrong",
"common.yes": "Yes",
"common.no": "No",
2026-07-10 12:54:45 +00:00
"api.err.unknown": "Something went wrong. Please try again.",
"api.err.network": "Cannot reach the server. Check your network or if the API is running.",
"api.err.400001": "Invalid request",
// Same sentence as backend 400003 / ValidatePasswordPolicy
"api.err.400003": "Password must be at least 12 characters with upper, lower, digit, and symbol",
"password.policy.hint": "Password must be at least 12 characters with upper, lower, digit, and symbol",
"password.policy.minLen": "Password must be at least 12 characters with upper, lower, digit, and symbol",
"password.policy.needUpper": "Password must be at least 12 characters with upper, lower, digit, and symbol",
"password.policy.needLower": "Password must be at least 12 characters with upper, lower, digit, and symbol",
"password.policy.needDigit": "Password must be at least 12 characters with upper, lower, digit, and symbol",
"password.policy.needSymbol": "Password must be at least 12 characters with upper, lower, digit, and symbol",
"api.err.400004": "Invalid or expired verification code",
"api.err.400020": "You cannot suspend your own account",
"api.err.400021": "Cannot demote or suspend the last active admin",
"api.err.401001": "Please sign in",
"api.err.401002": "Session expired. Please sign in again.",
"api.err.401003": "Account not found. Please sign in again.",
"api.err.401010": "Invalid email or password",
"api.err.403001": "Account suspended",
"api.err.403002": "Admin access required",
"api.err.404001": "Not found",
"api.err.404002": "This email is not registered",
"api.err.409001": "This email is already registered",
"api.err.500000": "Server error. Please try again later.",
"api.err.501000": "This feature is not implemented yet",
"api.ok.verifySent": "Verification code sent. Please check your email.",
"api.ok.verifyIssued": "Verification code issued",
"api.ok.resetSent": "Reset email sent. Please check your inbox.",
"api.ok.passwordUpdated": "Password updated",
"api.ok.loggedOut": "Signed out",
"api.ok.unbound": "Unbound",
2026-07-10 05:10:31 +00:00
"topbar.notifications": "Notifications",
"topbar.unread": "{n} unread",
"topbar.markAllRead": "Mark all read",
"topbar.noNotifications": "No notifications",
"topbar.jobsCenter": "Job center",
"topbar.moreOlder": "{n} older",
"topbar.account": "Account menu",
"role.admin": "Admin",
"role.member": "Member",
"role.verified": "Verified",
"role.unverified": "Unverified",
"login.title": "Sign in to Lapras",
"login.email": "Email",
"login.password": "Password",
"login.submit": "Sign in",
"login.submitting": "Signing in…",
"login.forgot": "Forgot password?",
"login.mockHint": "Admin demo@harbor.local / demo · member alice@harbor.local / alice",
2026-07-10 12:54:45 +00:00
"login.liveHint": "Live backend: admin@haixun.local / admin123 (gateway :8888)",
2026-07-10 05:10:31 +00:00
"forgot.title": "Forgot password",
"forgot.submit": "Send reset link",
"forgot.submitting": "Sending…",
"forgot.back": "Back to sign in",
2026-07-10 12:54:45 +00:00
"forgot.hint": "Enter your registered email. We'll send a reset link and code.",
2026-07-10 05:10:31 +00:00
"forgot.mockMail": "Reset email",
2026-07-10 12:54:45 +00:00
"forgot.openReset": "Enter code / reset password",
2026-07-10 05:10:31 +00:00
"forgot.retry": "Try again",
2026-07-10 12:54:45 +00:00
"forgot.nextStep": "Check your email for the code or link, then open the reset page to set a new password.",
2026-07-10 05:10:31 +00:00
"reset.title": "Set new password",
2026-07-10 12:54:45 +00:00
"reset.hint": "Enter email, verification code (from the email), and a new password.",
"reset.code": "Verification code",
"reset.codePh": "6-digit code from email",
"reset.needEmail": "Email is required",
"reset.needCode": "Verification code is required",
2026-07-10 05:10:31 +00:00
"reset.newPassword": "New password",
"reset.confirm": "Confirm password",
"reset.submit": "Update password",
"reset.submitting": "Updating…",
"reset.missingToken": "Missing token. Please request a new reset link.",
"verify.title": "Verify email",
"verify.pending": "Not verified",
"verify.body": "You're signed in, but features stay locked until you verify your email with the 6-digit code.",
"verify.code": "Verification code",
"verify.submit": "Verify",
"verify.submitting": "Verifying…",
"verify.resend": "Resend code",
"verify.sending": "Sending…",
"verify.logout": "Log out",
"verify.mockMail": "Verification email",
"verify.mockHint": "Enter the code:",
"verify.after": "After verification you can use Today, Studio, Patrol, and more.",
"settings.title": "Settings",
"settings.localeCurrency": "Language & currency",
"settings.locale": "Interface language",
"settings.currency": "Display currency",
"settings.currencyHint": "",
"settings.localeSaved": "Language and currency updated",
"settings.appearance": "Appearance",
"settings.theme": "Theme",
"settings.themeLight": "Light",
"settings.themeDark": "Dark",
"settings.themeSystem": "System",
"settings.themeHint": "",
"settings.themeSaved": "Theme updated",
"settings.themeToLight": "Switch to light",
"settings.themeToDark": "Switch to dark",
"settings.dataSource": "Data source",
2026-07-10 12:54:45 +00:00
"settings.dataSourceHint":
"mock = in-browser fake data; live = apps/backend gateway. Re-login after switching to live.",
"settings.dataSourceMock": "Mock (local)",
"settings.dataSourceLive": "Live (backend API)",
"settings.dataSourceCurrent": "Current",
"settings.dataSourceSwitchedLive":
"Switched to Live — re-login with backend account (admin@haixun.local / admin123)",
"settings.dataSourceSwitchedMock": "Switched back to Mock",
"settings.dataSourceLiveNeedGateway": "Requires gateway on :8888 (or Vite proxy /api)",
2026-07-10 05:10:31 +00:00
"settings.ai": "AI",
"settings.search": "Search",
"settings.member": "Account & sign-in",
"settings.usageCard": "AI / search quota",
"settings.usageCardHint": "",
"settings.viewUsage": "View usage",
"settings.editProfile": "Edit profile",
"settings.mockLogin": "demo@harbor.local / demo",
"settings.memberHint": "",
"usage.title": "Usage & plans",
"usage.desc": "",
"usage.creditsUsed": "Credits used this month",
"usage.remaining": "{n} left",
"usage.percentUsed": "{n}% used",
"usage.breakdown": "Breakdown",
"usage.plans": "Plans",
"usage.current": "Current",
"usage.inUse": "Active",
"usage.switchMock": "Switch plan",
"usage.perMonth": "credits / mo",
"usage.ledger": "Recent usage",
"usage.emptyTitle": "No usage this month",
"usage.emptyDesc": "",
"usage.planNote": "",
"usage.switched": "Switched to {name}",
"usage.meter.times": "{count} runs · {credits} credits",
"usage.meter.cap": "Soft cap {count}/{cap} runs",
"usage.plan.free.blurb": "Trial and light personal use",
"usage.plan.starter.blurb": "Small teams posting and patrolling daily",
"usage.plan.pro.blurb": "Multi-account, heavy AI and research",
"profile.title": "Profile",
"profile.desc": "",
"profile.accountStatus": "Account status",
"profile.basic": "Basics",
"profile.avatar": "Avatar",
"profile.avatarUpload": "Upload avatar",
"profile.avatarRemove": "Remove avatar",
2026-07-10 12:54:45 +00:00
"profile.avatarHint": "JPG / PNG / WebP, up to 5MB. Pick a file then Save basic info; Remove clears immediately.",
2026-07-10 05:10:31 +00:00
"profile.avatarSaved": "Avatar updated",
"profile.avatarCleared": "Avatar removed",
"profile.avatarFail": "Could not read image",
"profile.displayName": "Display name",
"profile.bio": "Bio (optional)",
"profile.timezone": "Timezone",
"profile.notifyEmail": "Email notifications",
"profile.password": "Change password (optional)",
"profile.currentPassword": "Current password",
"profile.newPassword": "New password",
"profile.confirmPassword": "Confirm new password",
"profile.emailVerified": "Email verified",
"profile.emailUnverified": "Email not verified",
"profile.roleAdmin": "Admin",
"profile.roleMember": "Member",
"profile.loginEmail": "Sign-in email: {email}",
"profile.verifiedAt": " · verified {time}",
"profile.goVerify": "Verify email",
"profile.roleTags": "Role tags: {labels}",
"profile.roleNote": "Roles are assigned by the system; re-verify after changing email.",
"profile.saveBasic": "Save profile",
"profile.updatePassword": "Update password",
"profile.saved": "Profile saved",
"profile.savedUnverified": "Saved. Verify your email before using features.",
"profile.saveFail": "Could not save",
"profile.needNewPassword": "Enter a new password",
"profile.passwordMismatch": "New passwords do not match",
"profile.needCurrentPassword": "Enter your current password",
2026-07-10 12:54:45 +00:00
"profile.wrongCurrentPassword": "Current password is incorrect",
2026-07-10 05:10:31 +00:00
"profile.passwordUpdated": "Password updated",
"profile.passwordFail": "Could not change password",
"profile.listJoin": ", ",
"profile.tenantUid": " · tenant {tenant} · uid {uid}",
2026-07-10 12:54:45 +00:00
"profile.inviteBadge": "Invite code",
"profile.inviteHint": "Share with friends to join; later events can use invite relations.",
"profile.gotoInvite": "View invites",
"invite.title": "Invites",
"invite.desc": "Invite codes and relations; admin view is a tree.",
"invite.tabs": "Invite views",
"invite.tab.mine": "My invites",
"invite.tab.tree": "Tree",
"invite.myCode": "My invite code",
"invite.codeLabel": "Invite code",
"invite.copyCode": "Copy",
"invite.copied": "Copied",
"invite.copyFail": "Copy failed",
"invite.stats": "{direct} direct · {total} in chain",
"invite.upline": "Invited by",
"invite.downlines": "Direct invites · {n}",
"invite.noUpline": "No inviter",
"invite.noDownline": "None yet",
"invite.directN": "{n} direct",
"invite.claimHint": "If you didnt enter a code at signup, add your inviters code here (cannot change later).",
"invite.claimLabel": "Invite code",
"invite.claimPh": "e.g. HX-DEMO01",
"invite.claimSubmit": "Bind",
"invite.claimOk": "Bound to {name}",
"invite.claimOkGeneric": "Inviter bound",
"invite.claimFail": "Could not bind",
"invite.claimLocked": "Already bound. Contact an admin to change.",
"invite.loadFail": "Failed to load",
"invite.treeEmpty": "No data",
"invite.treeSearch": "Search",
"invite.treeSearchPh": "Name / email / code",
"invite.treeCount": "{n} people",
"invite.treeMatchCount": "{n} matches · {total} total",
"invite.treeNoMatch": "No matches",
"invite.treeNoMatchHint": "Try another keyword",
"invite.clearSearch": "Clear",
"invite.moveTitle": "Reassign",
"invite.newParent": "Inviter",
"invite.root": "(None · standalone)",
"invite.confirmMove": "Confirm",
"invite.moved": "Reassigned “{name}” → “{parent}”",
"invite.moveFail": "Failed",
"invite.openFromAdmin": "Invites",
"invite.parentField": "Invited by",
"invite.orgPickRoot": "Pick a starting root (includes self-joined)",
"invite.orgRoots": "Roots",
"invite.orgPath": "Path",
"invite.orgChainN": "{n} in chain",
"invite.orgFocusStats": "{direct} direct · {total} in chain",
"invite.orgDirects": "Direct invites · {n}",
"invite.orgNoDirects": "No direct invites",
"invite.err.notFound": "Member not found",
"invite.err.notLoggedIn": "Not signed in",
"invite.err.needAdmin": "Admin access required",
"invite.err.memberNotFound": "Islander not found",
"invite.err.selfParent": "Cannot set yourself as inviter",
"invite.err.parentNotFound": "Inviter not found",
"invite.err.cycle": "Cannot place under your own invite chain (would create a cycle)",
"invite.err.repoMissing": "Invite data layer not loaded — please refresh the page",
"invite.err.alreadyBound": "You already have an inviter",
"invite.err.codeRequired": "Enter an invite code",
"invite.err.codeNotFound": "Invite code not found",
"invite.err.codeSelf": "You cant use your own code",
2026-07-10 05:10:31 +00:00
"admin.users.title": "Islanders",
"admin.users.desc": "",
"admin.users.needAdmin": "Admin access required",
"admin.users.list": "Islanders · {n}",
"admin.users.detail": "Islander detail",
"admin.users.pick": "Select an islander",
"admin.users.search": "Search name / uid",
"admin.users.searchPh": "Name, email, or uid",
"admin.users.create": "Add islander",
"admin.users.suspend": "Suspend",
"admin.users.unsuspend": "Restore",
"admin.users.suspended": "Suspended",
"admin.users.active": "Active",
"crew.title": "Accounts",
"crew.tab.accounts": "Accounts",
"crew.tab.personas": "Personas",
"crew.connect": "Connect account",
"crew.connecting": "Adding…",
"crew.refreshAll": "Refresh all sessions",
"crew.refreshing": "Refreshing…",
"crew.empty": "No accounts yet",
"crew.unusable": "Unavailable",
"crew.expires": "Expires {time}",
"crew.lastRefresh": "Last refresh {time}",
"crew.refreshSession": "Refresh session",
"crew.session.ok": "Session valid",
"crew.session.soon": "Expiring soon",
"crew.session.expired": "Session expired",
"crew.session.unknown": "Session unknown",
"crew.msg.refreshed": "@{user} session refreshed (~30 days)",
"crew.msg.refreshedAll": "Refreshed {n} account sessions",
"crew.msg.refreshFail": "Refresh failed",
"crew.confirmDelete": "Delete account @{user}?\nIt can no longer be used as lead / cast.",
"today.findTopic": "Find topics",
"today.pendingReplies": "Pending replies",
"today.pendingRepliesN": "Pending · {n}",
"today.newThread": "New thread",
"today.metricsAria": "Today metrics",
"today.metric.pending": "Pending",
"today.metric.pendingHint": "Patrol queue",
"today.metric.doneGoal": "Done / goal",
"today.metric.sentToday": "Sent today",
"today.metric.running": "{n} in progress",
"today.metric.sentDone": "Completed sends",
"today.metric.failed": "Send issues",
"today.metric.needAction": "Needs action",
"today.metric.ok": "All good",
"today.pending.title": "Pending replies · {n}",
"today.pending.empty": "Nothing pending",
"today.goScout": "Go patrol",
"today.pending.more": "{n} more →",
"today.pending.handle": "Handle in patrol",
"today.pending.start": "Start handling",
"today.topics.title": "Find topics",
"today.topics.empty": "No topics yet",
"today.goStudio": "Go to Studio",
"today.heat": "Heat {n}",
"today.topicAngle": "Good opening angle",
"today.moreInspire": "More inspiration",
"today.useTopic": "Start from topic",
"today.outbox.title": "Today's outbox",
"today.outbox.empty": "No sends today. Try",
"today.outbox.emptyMid": ", then check",
"today.outbox.emptyEnd": ".",
"today.outbox.summary": "Done {sent} · In progress {running} · Issues {failed}",
"today.badge.failed": "Failed",
"today.badge.scheduling": "Scheduled",
"today.badge.sending": "Sending",
"today.openOutbox": "Open outbox",
"today.accounts.title": "Account performance",
"today.accounts.empty": "No stats yet",
"today.postsCount": "{n} posts",
"today.views": "Views",
"today.likes": "Likes",
"today.repliesShort": "Replies",
"today.fullInsights": "Full insights · MoM charts",
"today.viewPosts": "View posts",
"today.manageAccounts": "Manage accounts",
"outbox.title": "Outbox",
"outbox.tabsAria": "Outbox tabs",
"outbox.tab.active": "Active",
"outbox.tab.history": "History",
"outbox.empty": "No outbox items",
"outbox.activeEmpty": "Nothing in progress",
"outbox.historyEmpty": "No history yet",
"outbox.historyN": "History ({n})",
"outbox.backActive": "Back to active ({n})",
"outbox.progress": "Progress {progress}",
"outbox.detail": "Details",
"outbox.deleting": "Deleting…",
"outbox.confirmDelete": "Delete outbox item “{title}”?\nThis cannot be undone.",
"outbox.deleted": "Deleted “{title}”",
"outbox.deleteFail": "Delete failed",
"outbox.status.scheduling": "Scheduling",
"outbox.status.active": "Sending",
"outbox.status.completed": "Completed",
"outbox.status.partial_failed": "Partial failure",
"outbox.status.cancelled": "Cancelled",
"outbox.detail.missingId": "Missing id",
"outbox.detail.notFound": "Outbox item not found",
"outbox.detail.markAllOk": "Mark all success",
"outbox.detail.markRootFail": "Mark root failed",
"outbox.detail.processing": "Working…",
"outbox.detail.delete": "Delete this",
"outbox.detail.back": "Back to list",
"outbox.detail.root": "Root post",
"outbox.detail.replyN": "Reply {n}",
"outbox.detail.retry": "Retry",
"outbox.detail.opFail": "Action failed",
"studio.title": "Studio",
"studio.account": "Account",
"studio.persona": "Persona",
"studio.personaReady": "Persona ready",
"studio.personaNotReady": "Persona not ready",
"studio.tab.posts": "My posts",
"studio.tab.mentions": "Mentions @",
"studio.tab.compose": "Compose",
"studio.tab.plays": "Plays",
"studio.tab.inspire": "Inspire",
"studio.tab.insights": "Insights",
"mentions.hint": "Who @ you. {n} pending. You can change account/persona per item (defaults from top bar).",
"mentions.scoutLink": "Patrol outreach",
"mentions.empty": "No mentions",
"mentions.status.pending": "Pending",
"mentions.status.replied": "Replied",
"mentions.status.skipped": "Skipped",
"mentions.reply": "Reply",
"mentions.skip": "Skip",
"mentions.draftLabel": "Reply draft",
"mentions.repliedPrefix": "Replied: {text}",
"mentions.needPersona": "Pick a ready persona before AI draft",
"mentions.fail": "Failed",
"mentions.marked": "Marked replied (@{user})",
"mentions.withImages": " · {n} images",
"compose.hint": "Single post (not a play). For multi-account threads use",
"compose.hintEnd": ".",
"compose.playsLink": "Plays",
"compose.personaOff": "Persona not ready: AI tools (mimic / analyze) disabled.",
"compose.title": "Title (optional)",
"compose.titlePh": "Helps identify in Outbox",
"compose.body": "Body",
"compose.bodyPh": "Write your post…",
"compose.tool.mimic": "Mimic",
"compose.tool.viral": "Viral analysis",
"compose.tool.research": "Research",
"compose.tool.image": "Image",
"compose.mimic.title": "Mimic another post",
"compose.mimic.source": "Source text",
"compose.mimic.sourcePh": "Paste the post to mimic…",
"compose.mimic.running": "Mimicking…",
"compose.mimic.run": "Mimic into body",
"compose.mimic.done": "Mimic done — edit as needed",
"compose.viral.title": "Viral analysis",
"compose.viral.hint": "Hooks, structure, and copyable patterns from source or body.",
"compose.viral.source": "Target (empty = use body)",
"compose.viral.running": "Analyzing…",
"compose.viral.run": "Analyze",
"compose.viral.result": "Analysis",
"compose.viral.done": "Viral analysis done",
"compose.viral.needText": "Paste a reference or write the body first",
"compose.research.title": "Research notes",
"compose.research.q": "Keywords",
"compose.research.qPh": "e.g. fragrance-free detergent sensitive skin",
"compose.research.running": "Searching…",
"compose.research.insert": "Insert selected into body",
"compose.research.inserted": "Inserted {n} notes",
"compose.image.title": "Generate image",
"compose.image.prompt": "Scene description",
"compose.image.promptPh": "Empty = summarize from body",
"compose.image.running": "Generating…",
"compose.image.run": "Generate image",
"compose.image.done": "Image added",
2026-07-10 12:54:45 +00:00
"compose.scheduleAt": "Publish at",
"compose.scheduleHint": "Outbox will send at this time. Use “Now” for ASAP.",
"compose.scheduleNow": "Now",
2026-07-10 05:10:31 +00:00
"compose.publish": "Send to Outbox",
"compose.publishing": "Sending…",
"compose.publishFail": "Send failed",
"compose.fail": "Failed",
"compose.attachN": "{n} images",
"compose.personaStatus": "Persona: {status}",
"compose.ready": "ready",
"compose.notReady": "not ready",
"posts.sync": "Resync Threads",
"posts.syncing": "Syncing…",
"posts.syncedAt": "Synced {time}",
"posts.notSynced": "Not synced",
"posts.syncDone": "Synced Threads metrics (likes / replies / reposts / quotes / views / shares)",
"posts.empty": "No posts yet",
"posts.openThreads": "Open Threads",
"posts.insight": "Insight: {text}",
"posts.review": "Review: {text}",
"posts.formulaResult": "Structure analysis",
"posts.collapseReplies": "Collapse replies",
"posts.repliesBtn": "Replies ({total}) · pending {pending}",
"posts.replyRoot": "Reply to post",
"posts.analyzing": "Analyzing…",
"posts.reanalyze": "Re-analyze structure",
"posts.analyze": "Analyze structure",
"posts.mimicThis": "Mimic this",
"posts.rootDraft": "Root reply draft",
"posts.filter.pending": "Pending ({n})",
"posts.filter.replied": "Replied ({n})",
"posts.filter.all": "All ({n})",
"posts.noPending": "No pending replies",
"posts.noReplied": "No replied items yet",
"posts.noReplies": "No replies yet",
"posts.status.pending": "Pending",
"posts.status.replied": "Replied",
"posts.likesN": "{n} likes",
"posts.childCount": "{n} child replies",
"posts.mine": "Ours",
"posts.replyThis": "Reply",
"posts.replyAgain": "Reply again",
"posts.replyTo": "Reply to @{user}",
"posts.replyAgainTo": "Reply again to @{user}",
"posts.needPersona": "Pick a ready persona before AI draft",
"posts.genFail": "Generate failed",
"posts.needText": "Generate or type a reply first",
"posts.sent": "Sent as @{user}",
"posts.sentImages": " ({n} images)",
"posts.accountFallback": "account",
"posts.sendFail": "Send failed",
"posts.analyzeDone": "Structure analysis done (manual)",
"posts.analyzeFail": "Analyze failed",
"wizard.newTitle": "New play",
"wizard.editTitle": "Edit play",
"wizard.prev": "Back",
"wizard.next": "Next",
"wizard.err.topic": "Enter a topic",
"wizard.err.lead": "Select a lead account",
"wizard.err.leadUnusable": "Lead account unavailable",
"wizard.submitFail": "Submit failed",
"wizard.unnamedPlay": "Untitled play",
"wizard.step.topic": "Topic",
"wizard.step.crew": "Cast",
"wizard.step.script": "Script",
"wizard.step.preview": "Preview",
"wizard.step.schedule": "Schedule",
"wizard.step.submit": "Submit",
"wizard.stepperAria": "Wizard steps",
"wizard.topic.title": "1. What is this thread about?",
"wizard.topic.name": "Title (optional)",
"wizard.topic.namePh": "e.g. Weekend coffee",
"wizard.topic.topic": "One-line topic",
"wizard.topic.topicPh": "What should this thread discuss?",
"wizard.topic.aiView": "AI persona view",
"wizard.topic.personaNotReady": "Persona not ready",
"wizard.topic.generating": "Generating…",
"wizard.topic.aiSuggest": "AI suggest",
"wizard.topic.quickFill": "Quick fill",
"wizard.topic.sampleTitle": "Weekend coffee chat",
"wizard.topic.sampleTopic": "Looking for a reliable café this weekend — lots of outlets, stay-all-day friendly.",
"wizard.topic.aiTitle": "AI topic",
"wizard.topic.personaOpen": "{name} opens",
"wizard.crew.title": "2. Cast",
"wizard.crew.lead": "Lead",
"wizard.crew.noUsable": "No usable accounts",
"wizard.crew.unusable": "Unavailable",
"wizard.crew.cast": "Supporting",
"wizard.script.title": "3. Lines",
"wizard.script.persona": "Persona",
"wizard.script.personaNotReady": "Persona not ready",
"wizard.script.root": "Root post",
"wizard.script.replyN": "Reply {n}",
"wizard.script.generating": "Generating…",
"wizard.script.ai": "AI draft",
"wizard.script.account": "Account: {name}",
"wizard.script.noLead": "(no lead)",
"wizard.script.speaker": "Speaker",
"wizard.script.leadTag": "(lead)",
"wizard.script.text": "Copy",
"wizard.script.rootPh": "Root post text…",
"wizard.script.replyPh": "Reply text…",
"wizard.script.addReply": "Add reply step",
"wizard.preview.title": "4. Preview the thread",
"wizard.preview.unknown": "Unknown",
"wizard.preview.unknownAccount": "Unknown account",
"wizard.preview.root": "Root",
"wizard.preview.leadTalk": "lead reply",
"wizard.preview.empty": "(empty)",
"wizard.schedule.title": "5. When to send",
"wizard.schedule.start": "First post (root) time",
"wizard.schedule.interval": "Reply interval (minutes)",
"wizard.schedule.intervalHint": "Relative to previous step",
"wizard.submit.title": "6. Submit schedule",
"wizard.submit.body": "Confirm to send “{title}” ({n} steps) to Outbox and publish in order.",
"wizard.submit.unnamed": "Untitled",
"wizard.submit.root": "Root",
"wizard.submit.replyN": "Reply {n}",
"wizard.submit.submitting": "Submitting…",
"wizard.submit.run": "Submit to Outbox",
"reply.account": "Reply as",
"reply.persona": "Persona",
"reply.notReady": "This persona is not ready for AI draft (you can still type and send).",
"reply.draft": "Reply draft",
"reply.attach": "Attach",
"reply.generating": "Generating…",
"reply.ai": "AI draft",
"reply.sending": "Sending…",
"reply.send": "Send",
"image.attach": "Attach",
"image.attachFail": "Attach failed",
"image.attachedAria": "Attached images",
"image.alt": "Attachment",
"image.named": "Image {n}",
"image.remove": "Remove image",
"image.full": "Full ({max})",
"image.more": "Add more ({n}/{max})",
"metrics.aria": "Post metrics",
"metrics.like": "Likes",
"metrics.reply": "Replies",
"metrics.repost": "Reposts",
"metrics.quote": "Quotes",
"metrics.view": "Views",
"metrics.share": "Shares",
"metrics.type.quote": "Quote",
"metrics.type.reply": "Reply",
"metrics.type.image": "Image",
"metrics.type.video": "Video",
"metrics.type.carousel": "Carousel",
"metrics.type.repost": "Repost",
"metrics.type.text": "Text",
"metrics.type.post": "Post",
"jobs.title": "Jobs",
"jobs.startDemo": "Start demo job",
"jobs.empty": "No jobs yet",
"jobs.total": "{n} total",
"jobs.showing": " · showing first {n}",
"jobs.detail": "Details",
"jobs.loadMore": "Load more ({n} more)",
"jobs.notFound": "Job not found",
"jobs.progress": "Progress {n}%",
"jobs.updated": "Updated {time}",
"jobs.backList": "Back to list",
"plans.title": "Change plan",
"plans.current": "Current plan",
"plans.perMonth": "/mo",
"plans.monthlyCredits": "{n} credits / month",
"plans.usageLink": "Usage",
"plans.inUse": "Active",
"plans.recommended": "Recommended",
"plans.creditsPerMonth": "{n} credits / month",
"plan.cta.current": "Current plan",
"plan.cta.upgrade": "Upgrade",
"plan.cta.downgrade": "Downgrade",
"plan.cta.switch": "Switch",
"plan.free.headline": "Trial and light personal use",
"plan.free.bullet1": "{n} AI/search credits per month",
"plan.free.bullet2": "Full product: Studio, Patrol, Outbox",
"plan.free.bullet3": "Good for learning the flow",
"plan.free.bullet4": "Upgrade anytime",
"plan.free.right1": "Full access to accounts, Studio, Patrol, Outbox, jobs, and inspiration.",
"plan.free.right2": "Fixed monthly credits for copy, research, search, and images.",
"plan.free.right3": "After the cap, wait for next month or upgrade (unless an admin turns off limits).",
"plan.free.quota1": "{n} credits allocated each month.",
"plan.free.quota2": "Reference: copy {copy}, research {research}, search {search}, image {image} runs.",
"plan.free.note1": "No payment required; confirms immediately.",
"plan.free.note2": "Invoice rules will be defined when billing goes live.",
"plan.starter.headline": "Small teams posting and patrolling daily",
"plan.starter.bullet1": "{n} credits / month (about 6× Free)",
"plan.starter.bullet2": "Steady posting, replies, and patrol",
"plan.starter.bullet3": "Fits a 13 person cadence",
"plan.starter.bullet4": "Takes effect right after payment",
"plan.starter.right1": "After payment this account becomes Starter; the month uses the new quota.",
"plan.starter.right2": "Credits support regular posts, reply drafts, and scheduled patrol.",
"plan.starter.right3": "Same features as Free; you buy more headroom.",
"plan.starter.quota1": "{n} credits / month · {price}.",
"plan.starter.quota2": "Reference: copy {copy}, research {research}, search {search}, image {image} runs.",
"plan.starter.note1": "Plan changes only after successful payment.",
"plan.starter.note2": "Resets on calendar month; unused credits do not roll over.",
"plan.pro.headline": "Multi-account, heavy AI and research",
"plan.pro.bullet1": "{n} credits / month (about 4× Starter)",
"plan.pro.bullet2": "High-volume copy, research, and images",
"plan.pro.bullet3": "Built for agencies and multi-brand work",
"plan.pro.bullet4": "Takes effect right after payment",
"plan.pro.right1": "After payment this account becomes Pro; the month uses Pro quota.",
"plan.pro.right2": "Fits multi-account replies and deep research with less risk of running out mid-month.",
"plan.pro.right3": "Same features; you buy capacity and pace.",
"plan.pro.quota1": "{n} credits / month · {price}.",
"plan.pro.quota2": "Reference: copy {copy}, research {research}, search {search}, image {image} runs.",
"plan.pro.note1": "Failed payment does not change your plan.",
"plan.pro.note2": "After payment you can find receipts in billing history.",
"checkout.title": "Confirm plan",
"checkout.pickFirst": "Please choose a plan first.",
"checkout.viewPlans": "View plans",
"checkout.cardLast4Required": "Enter the last 4 digits of your card",
"checkout.cardNameRequired": "Enter the cardholder name",
"checkout.fail": "Could not complete",
"checkout.confirmFree": "Confirm switch to Free",
"checkout.payAndAction": "{action} and pay {price}",
"checkout.subscribe": "Subscription",
"checkout.perMonth": "/mo",
"checkout.monthlyCredits": "{n} credits per month",
"checkout.youGet": "What you get",
"checkout.quota": "Quota",
"checkout.notes": "Notes",
"checkout.cardholder": "Cardholder",
"checkout.cardLast4": "Last 4 digits",
"checkout.amountDue": "Amount due",
"checkout.billedMonthly": "{name} · billed monthly",
"checkout.already": "Already on this plan",
"checkout.processing": "Processing…",
"checkout.currentPlan": "Current plan",
"checkout.pickOther": "Choose another plan",
"checkout.cancel": "Cancel",
"usage.widget.titleUsed": "{name} · used {used}/{cap} credits",
"usage.widget.titleUnlimited": "{name} · unlimited",
"usage.widget.ariaUsed": "Used {used} of {cap} credits",
"usage.widget.dialog": "Plan and usage",
"usage.widget.currentPlan": "Current plan",
"usage.widget.unlimited": "Unlimited",
"usage.widget.perMonth": "/mo",
"usage.widget.monthUsage": "This month",
"usage.widget.remaining": "{n} credits left",
"usage.widget.leftShort": "{n} left",
"usage.widget.overShort": "Over",
"usage.widget.upgradeShort": "Upgrade",
"usage.widget.upgrade": "Upgrade",
"usage.widget.includes": "This plan includes",
"usage.widget.nudge": "You're running low this month. Upgrade for more credits right away.",
"usage.widget.changePlan": "Change plan",
"usage.widget.usageDetail": "Usage details",
"usage.meter.ai_copy": "AI copy",
"usage.meter.ai_research": "AI research",
"usage.meter.web_search": "Search",
"usage.meter.ai_image": "AI image",
"usage.meter.barAria": "{label} {count} runs, {credits} credits, cap {cap}",
"usage.ledger.costAria": "Used {n} credits",
"usage.chart.period": "Period",
"usage.chart.allocated": "Allocated",
"usage.chart.consumed": "Used",
"usage.chart.pctTitle": "Usage as share of allocation",
"usage.chart.aria": "Allocation and usage",
"usage.chart.colAria": "{label}: allocated {purchased}, used {consumed}",
2026-07-10 12:54:45 +00:00
"settings.provider": "Provider",
"settings.model": "Model",
"settings.aiUnifiedHint": "Copy, research, and expand all share one provider and model.",
2026-07-10 05:10:31 +00:00
"settings.fetchModels": "Fetch models",
"settings.fetchingModels": "Loading…",
2026-07-10 12:54:45 +00:00
"settings.apiKey": "API key",
2026-07-10 05:10:31 +00:00
"settings.configured": "Configured",
"settings.notConfigured": "Not set",
"settings.modelsLoaded": "Loaded models for {provider}",
"settings.aiSaved": "AI settings saved",
"settings.searchSaved": "Search settings saved",
2026-07-10 12:54:45 +00:00
"settings.searchProvider": "Search provider",
"settings.expand": "Expand strategy",
"settings.exaKey": "Exa API key",
"settings.devMode": "Developer mode (crawler test patrol)",
"settings.devModeHint": "When on, test patrol can use the Chrome crawler; live publish/replies still use the API. Download the extension to sync Threads session.",
"settings.ext.title": "Chrome extension",
"settings.ext.desc": "Developer mode needs this extension to sync Threads session from Chrome into Lapras.",
"settings.ext.step1": "Download and unzip to get the haixun-threads-sync folder",
"settings.ext.step2": "Open chrome://extensions and enable Developer mode",
"settings.ext.step3": "Click Load unpacked and select the unzipped folder",
"settings.ext.step4": "Set this sites URL in the extension options, then refresh Lapras",
"settings.ext.download": "Download extension (ZIP)",
2026-07-10 05:10:31 +00:00
"forgot.fail": "Request failed",
"forgot.mockHint": "In production this goes to email; here is a direct link:",
2026-07-10 12:54:45 +00:00
"forgot.checkInbox": "Please check your inbox (and spam).",
2026-07-10 05:10:31 +00:00
"reset.mismatch": "Passwords do not match",
"reset.fail": "Reset failed",
"reset.cardTitle": "Reset password",
"reset.redirecting": "Redirecting to sign in…",
"reset.loginNow": "Sign in now",
2026-07-10 12:54:45 +00:00
"reset.passwordPh": "Password must be at least 12 characters with upper, lower, digit, and symbol",
"reset.forgotLink": "Request a new reset",
2026-07-10 05:10:31 +00:00
"verify.sendFail": "Could not send",
"verify.fail": "Verification failed",
"verify.success": "Email verified. You can use Lapras now.",
"verify.codePh": "6-digit code",
"verify.currentAccount": "Account: {email}",
"login.brandTitle": "巡樓 · Lapras",
"common.listSep": ", ",
"common.dash": "—",
"scout.title": "Patrol",
"scout.today": "Today",
"scout.purposeValue": "Pain-point replies",
"scout.purposeActivity": "Activity short replies",
"scout.goal": "Daily goal (posts)",
"scout.progress": "Progress {done}/{goal}",
"scout.intent": "What to find / reply to",
"scout.keyword": "Keywords",
"scout.intentPh": "e.g. seasonal scalp itch, truly fragrance-free, outlets on weekends",
"scout.keywordPh": "e.g. weekend coffee remote",
"scout.productOptional": "Product (optional)",
"scout.noProduct": "No product",
"scout.brandFallback": "Brand",
"scout.placement": "Placement: {label}",
"scout.painPart": " · pain “{pain}”",
"scout.noProductsBefore": "No products yet. Add some under",
"scout.noProductsAfter": ".",
"scout.start": "Start",
"scout.startMore": "Fetch more",
"scout.fetching": "Fetching…",
"scout.runs": "Patrol batches",
"scout.runCount": "Batch ({n})",
"scout.runSelectAria": "Switch patrol batch",
"scout.runPending": "{n} pending · ",
"scout.runDone": "Cleared · ",
"scout.runTotal": " ({n} posts)",
"scout.deleteRun": "Delete this batch",
"scout.deleting": "Deleting…",
"scout.now": "Now this post",
"scout.emptyBatch": "Nothing pending in this batch",
"scout.draft": "Reply draft",
"scout.draftPhActivity": "Short reply…",
"scout.draftPhValue": "Empathize → suggest…",
"scout.sendAccount": "Send from account",
"scout.noAccount": "No usable accounts",
"scout.personaForRegen": "Persona (for regen)",
"scout.notReady": " (not ready)",
"scout.skip": "Skip",
"scout.regen": "Regen",
"scout.send": "Send",
"scout.sending": "Sending…",
"scout.needAccountBefore": "Connect a usable account under",
"scout.needAccountAfter": "first.",
"scout.knowledge": "Related knowledge",
"scout.knowledgeWithLabel": "Related · {label}",
"scout.knowledgeLearn": "Related · to learn",
"scout.collapseKnowledge": "Collapse knowledge",
"scout.expandLearn": "Expand · {n} notes",
"scout.expandKnowledge": "Expand knowledge",
"scout.deleteKnowledgeRun": "Delete this batch's knowledge & hits",
"scout.loadingKnowledge": "Preparing related knowledge…",
"scout.notesCount": "{n} notes",
"scout.noKnowledge": "No related knowledge yet",
"scout.product": "Product",
"scout.painsSolved": "Pains we solve",
"scout.focus": "Focus",
"scout.all": "All",
"scout.noWebSummary": "No web summaries yet",
"scout.queue": "Queue · {n}",
"scout.collapseQueue": "Collapse queue",
"scout.expandQueue": "Expand queue",
"scout.noOtherPending": "No other pending",
"scout.learnPoints": "Key takeaways",
"scout.replyHooks": "Reply hooks",
"scout.badgeCore": "Closest to topic",
"scout.unnamedRun": "Unnamed batch",
"scout.thisRun": "this batch",
"scout.confirmDeleteRun": "Delete patrol batch “{label}”?\\nHits and related knowledge will be removed. This cannot be undone.",
"scout.deletedRun": "Deleted batch “{label}”",
"scout.deleteRunFail": "Failed to delete batch",
"scout.needKeyword": "Enter keywords first",
"scout.needIntent": "Write what you're looking for",
"scout.productMissing": "Selected product is not in the list. Please reselect.",
"scout.defaultLabel": "Patrol",
"scout.newRunActivity": "New batch “{label}” · {n} pending",
"scout.newRunValue": "New batch “{label}” · {n} posts · handle “Now this post”",
"scout.knowledgeReady": "“{label}” knowledge ready · {n} notes",
"scout.patrolFail": "This patrol failed",
"scout.draftFail": "Draft failed",
"scout.skipped": "Skipped",
"scout.noDraft": "No draft to send",
"scout.accountFallback": "account",
"scout.sent": "Sent (@{who}) · today {done}/{goal}",
"scout.sendFail": "Send failed",
"scout.confirmDeletePost": "Delete this hit?",
"scout.stanceActivity": "Short reply · activity",
"scout.stanceProduct": "Empathy · soft product",
"scout.stanceRelation": "Engage · build rapport",
"scout.tier.core": "Closest",
"scout.tier.coreHint": "Directly on the pain/keywords — read first",
"scout.tier.adjacent": "Adjacent",
"scout.tier.adjacentHint": "Nearby context, broaden search",
"scout.tier.broad": "Broad",
"scout.tier.broadHint": "Background & contrast — optional",
"scout.relation.solves_pain": "Hits the pain",
"scout.relation.nearby_scene": "Nearby scene",
"scout.relation.myth": "Myth-busting",
"scout.relation.contrast": "Contrast shopping",
"scout.relation.background": "Background",
"brands.title": "Brands",
"brands.railAria": "Brand list",
"brands.railLabel": "Your brands",
"brands.add": "Add",
"brands.brandName": "Brand name",
"brands.brandNamePh": "e.g. your brand",
"brands.creating": "Creating…",
"brands.createBrand": "Create brand",
"brands.searchAria": "Search brands",
"brands.searchPh": "Search brands…",
"brands.empty": "No brands yet",
"brands.noMatch": "No matches",
"brands.selectAria": "Select brand",
"brands.pickOne": "Pick a brand",
"brands.inUseHint": "Active · used for patrol and studio",
"brands.inUse": "Active",
"brands.tabInfo": "Brand info",
"brands.tabProducts": "Products",
"brands.tabProductsN": "Products ({n})",
"brands.displayName": "Name",
"brands.brief": "Summary",
"brands.briefPh": "One line about this brand",
"brands.audience": "Audience",
"brands.audiencePh": "Who cares and why",
"brands.goals": "Goals",
"brands.goalsPh": "What you want on Threads",
"brands.saving": "Saving…",
"brands.deleteBrand": "Delete brand",
"brands.searchProductAria": "Search products",
"brands.searchProductPh": "Search products…",
"brands.addProduct": "Add product",
"brands.noProducts": "No products yet",
"brands.hasLink": "Has link",
"brands.painLabel": "Pains ",
"brands.editProduct": "Edit product",
"brands.newProduct": "New product",
"brands.importFromUrl": "Import from product URL",
"brands.fetching": "Fetching…",
"brands.fetch": "Fetch",
"brands.pains": "Pain points",
"brands.painsPh": "One per line",
"brands.tags": "Tags",
"brands.tagsPh": "Comma-separated",
"brands.intro": "Description",
"brands.link": "Link",
"brands.update": "Update",
"brands.createItem": "Add",
"brands.needName": "Enter a name",
"brands.created": "Created “{name}”",
"brands.createFail": "Create failed",
"brands.saved": "Saved",
"brands.saveFail": "Save failed",
"brands.confirmDelete": "Delete “{name}”?",
"brands.deleted": "Deleted",
"brands.deleteFail": "Delete failed",
"brands.fetchFail": "Fetch failed",
"brands.needLabelContext": "Name and description are required",
"brands.productUpdated": "Updated",
"brands.productAdded": "Added",
"brands.confirmDeleteProduct": "Delete this product?",
"insights.title": "Account performance",
"insights.account": "Account",
"insights.noAccount": "No accounts",
"insights.syncing": "Syncing…",
"insights.syncPosts": "Sync posts",
"insights.myPosts": "My posts",
"insights.pickAccount": "Select an account",
"insights.goAccounts": "Accounts",
"insights.kpiMonth": "This month",
"insights.monthViews": "Views this month",
"insights.monthLikes": "Likes this month",
"insights.monthReplies": "Replies this month",
"insights.engRate": "Engagement",
"insights.vsPrev": "vs last month",
"insights.avgNear": "Recent avg {rate}",
"insights.trendTitle": "Trends & analysis · @{user}",
"insights.metricViews": "Views",
"insights.metricLikes": "Likes",
"insights.metricReplies": "Replies",
"insights.metricPosts": "Posts",
"insights.metricPostsFull": "Posts",
"insights.chartMetrics": "Chart metric",
"insights.barsAria": "Recent months {metric}; click a bar for analysis",
"insights.barsLabel": "{metric} · last {n} months",
"insights.clickBar": " · click bar for analysis",
"insights.pickMonthAria": "Select month",
"insights.barTitle": "{label}: {value}{est} · click for analysis",
"insights.est": " (est.)",
"insights.monthSuffix": "{m}",
"insights.sparkAria": "Trend line; click a node to select month",
"insights.analysisOf": "{label} analysis",
"insights.producedAt": "Generated {time}",
"insights.hasEstimate": " · includes estimates",
"insights.viewsVsPrev": " · views vs prev {delta}",
"insights.statPosts": "Posts",
"insights.statViews": "Views",
"insights.statLikes": "Likes",
"insights.statReplies": "Replies",
"insights.conclusions": "Takeaways",
"insights.recommendations": "Recommendations",
"insights.highlights": "Month highlights",
"insights.findTopics": "Find topics",
"insights.goScout": "Go patrol",
"insights.selectMonth": "Select a month",
"insights.topPosts": "Top posts",
"insights.noPosts": "No posts yet",
"insights.postStats": "Views {views} · likes {likes} · replies {replies}",
"insights.openThreads": "Open Threads",
"insights.zeroPct": "0%",
"plays.tabOwn": "My posts",
"plays.tabLink": "Threads link",
"plays.noPosts": "No posts yet",
"plays.targetPost": "Target post",
"plays.likesSuffix": " ({n} likes)",
"plays.linkCard": "Paste Threads link",
"plays.postLink": "Post URL",
"plays.resolving": "Resolving…",
"plays.resolve": "Resolve link",
"plays.resolveHint": "After resolve, schedule your accounts to reply under that post.",
"plays.targetOwn": "Target post (yours)",
"plays.openThreads": "Open Threads",
"plays.external": "External post",
"plays.addScheme": "New scheme",
"plays.schemeCount": "{n} schemes for this target",
"plays.noSchemes": "No schemes yet",
"plays.replyCount": "{n} replies",
"plays.editTitle": "Edit: {title}",
"plays.schemeName": "Scheme name",
"plays.schemeNamePh": "e.g. Scheme A · soft engage",
"plays.speakersOwn": "Accounts (post owner always included)",
"plays.speakers": "Accounts",
"plays.postOwner": " (post owner)",
"plays.noAccounts": "No usable accounts. Connect Threads first.",
"plays.interval": "Interval (min)",
"plays.applyInterval": "Apply interval",
"plays.aiEmpty": "AI fill empty",
"plays.aiBusy": "Generating…",
"plays.replies": "Replies ({n})",
"plays.stepN": "Reply {n}",
"plays.who": "Who",
"plays.personaOpt": "Persona (optional)",
"plays.brandOpt": "Brand (optional)",
"plays.reply": "Reply",
"plays.attach": "Images",
"plays.addOne": "Add one",
"plays.saving": "Saving…",
"plays.saveScheme": "Save scheme",
"plays.submitting": "Submitting…",
"plays.submitOutbox": "Submit to Outbox",
"plays.closeEdit": "Close editor",
"plays.noTarget": "No target post yet",
"plays.resolved": "Link resolved",
"plays.resolveFail": "Resolve failed",
"plays.filled": "Generated {n}",
"plays.needTarget": "Select a target post first",
"plays.saved": "Scheme saved",
"plays.saveFail": "Save failed",
"plays.submitted": "Sent to Outbox",
"plays.submitFail": "Submit failed",
"plays.confirmDelete": "Delete this scheme?",
"plays.accountFallback": "account",
"inspire.loading": "Loading…",
"inspire.trendsAria": "What's hot on Threads",
"inspire.trendsLabel": "Hot on Threads",
"inspire.refresh": "Refresh",
"inspire.clearChat": "Clear chat",
"inspire.pinAsElement": "Apply as element",
"inspire.you": "You",
"inspire.ai": "AI",
"inspire.system": "System",
"inspire.useDraft": "Use this draft",
"inspire.openPlay": "Open play",
"inspire.generating": "Generating…",
"inspire.thinking": "Thinking…",
"inspire.pinnedAria": "Applied this round",
"inspire.pinned": "Applied",
"inspire.pickRight": "Pick elements on the right",
"inspire.unpinTitle": "Click to unapply",
"inspire.inputAria": "Talk to AI",
"inspire.inputPh": "What to write? Or shorter, more casual…",
"inspire.send": "Send",
"inspire.generate": "Generate",
"inspire.library": "Element library",
"inspire.addNew": "+ Add",
"inspire.kind": "Type",
"inspire.kindRole": "Role prompt",
"inspire.kindSnippet": "Snippet",
"inspire.kindTrendNote": "Trend note",
"inspire.kindBrand": "Brand",
"inspire.kindTrend": "Trend",
"inspire.name": "Name",
"inspire.namePh": "e.g. pro Threads writer",
"inspire.body": "Content (goes into prompt)",
"inspire.bodyPh": "You are a…",
"inspire.saveElement": "Save to library",
"inspire.citeBrand": "Cite brand",
"inspire.applied": "Applied",
"inspire.clickApply": "Click to apply",
"inspire.noBrands": "No brands yet",
"inspire.appliedToggle": "Applied · click again to remove",
"inspire.deleteAria": "Delete",
"inspire.needInput": "Type a line first, or generate directly",
"inspire.fail": "Failed",
"inspire.wantWrite": "Want to write about {label}: {summary}",
"inspire.trendBody": "Topic: {label}. {summary}",
"inspire.pinnedTrend": "Applied trend {label}",
"inspire.needTitleBody": "Name and content required",
"inspire.added": "Added to library",
"inspire.addFail": "Add failed",
"inspire.confirmRemove": "Remove this from the library?",
"inspire.confirmClear": "Clear chat? (library kept)",
"inspire.genMessage": "Write a Threads post from the applied elements",
"persona.add": "New persona",
"persona.empty": "No personas yet",
"persona.emptyDesc": "Add one and analyze it for drafting.",
"persona.statusReady": "ready",
"persona.statusAnalyzing": "analyzing",
"persona.statusPending": "pending",
"persona.default": "Default",
"persona.backList": "← Personas",
"persona.tabOverview": "Overview",
"persona.tabAnalyze": "Analyze",
"persona.tabFingerprint": "Fingerprint",
"persona.tabPreview": "Preview",
"persona.name": "Name",
"persona.brief": "Brief",
"persona.briefPh": "Who, for whom, core message…",
"persona.avoid": "Guardrails · banned words (comma-separated)",
"persona.guardChars": "{n} chars",
"persona.banAi": " · ban AI tone",
"persona.notReadySuffix": " · not ready",
"persona.setDefault": "Set as default",
"persona.modeAccount": "Public account",
"persona.modeText": "Paste text",
"persona.username": "Threads username",
"persona.fromBound": "From linked account",
"persona.select": "Select…",
"persona.crawlAnalyze": "Crawl public posts & analyze",
"persona.crawlBusy": "Crawling / analyzing…",
"persona.refText": "Reference text (--- separates posts)",
"persona.refTextPh": "First post…\n\n---\n\nSecond post…",
"persona.sourceLabel": "Source note (optional)",
"persona.sourcePh": "My old posts",
"persona.analyzeText": "Analyze from text",
"persona.analyzeBusy": "Analyzing…",
"persona.sampleMeta": "Samples {n}",
"persona.sourceManual": "Pasted",
"persona.analyzeHint": "After analysis, 8D summaries appear here.",
"persona.fingerprintHint": "Main voice for drafting. Edit catchphrases, rhythm, bans; Studio/replies use this.",
"persona.fingerprint": "Language fingerprint",
"persona.fingerprintPh": "Filled after analysis…",
"persona.saveFingerprint": "Save fingerprint",
"persona.tryGen": "Preview root + reply",
"persona.notReadyMsg": "Persona not ready",
"persona.rootPost": "Root post",
"persona.reply": "Reply",
"persona.hidePrompt": "Hide prompt block",
"persona.showPrompt": "Show injected prompt",
"persona.promptBlock": "prompt block (post)",
"persona.pickOne": "Pick a persona",
"persona.pickDesc": "Or add one to start analyzing.",
"persona.created": "Created — finish account crawl or paste text under Analyze",
"persona.saved": "Saved",
"persona.textDone": "Text analysis done · {n} segments → ready",
"persona.analyzeFail": "Analysis failed",
"persona.reading": "Reading public posts…",
"persona.accountDone": "@{user} · {n} posts → ready",
"persona.setDefaultMsg": "“{name}” set as default",
"persona.confirmDelete": "Delete persona “{name}”?",
"persona.deleted": "Persona deleted",
"persona.needReady": "Finish analysis first (ready)",
"persona.dim.d1Tone": "D1 Tone",
"persona.dim.d2Structure": "D2 Structure",
"persona.dim.d3Interaction": "D3 Interaction",
"persona.dim.d4Topics": "D4 Topics",
"persona.dim.d5Rhythm": "D5 Rhythm",
"persona.dim.d6Visual": "D6 Visual",
"persona.dim.d7Conversion": "D7 Conversion",
"persona.dim.d8Risk": "D8 Risk",
"admin.users.loadFail": "Load failed",
"admin.users.created": "Added islander “{name}” · copy the password below",
"admin.users.createFail": "Create failed",
"admin.users.unlimitedOn": "“{name}” set to unlimited (usage still counted)",
"admin.users.unlimitedOff": "“{name}” back to plan limits",
"admin.users.updateFail": "Update failed",
"admin.users.planSet": "“{name}” plan → {plan}",
"admin.users.confirmSuspend": "Suspend “{name}”?\\nThey will not be able to sign in.",
"admin.users.confirmUnsuspend": "Restore “{name}”?\\nThey can sign in again.",
"admin.users.didSuspend": "Suspended “{name}”",
"admin.users.didUnsuspend": "Restored “{name}”",
"admin.users.suspendFail": "Suspend failed",
"admin.users.unsuspendFail": "Restore failed",
"admin.users.markedVerified": "Marked {name} as email verified",
"admin.users.markedUnverified": "Marked {name} as unverified",
"admin.users.rolesUpdated": "Updated roles for {name}: {roles}",
"admin.users.rolesFail": "Role update failed",
"admin.users.confirmReset": "Reset password for “{name}”?\\nTemp password stays visible until you close it (survives refresh).",
"admin.users.resetDone": "Reset password for {name} (shown below — copy then close)",
"admin.users.resetFail": "Reset failed",
"admin.users.copied": "Copied to clipboard",
"admin.users.copyFail": "Copy failed — select the password manually",
"admin.users.confirmDismissTemp": "After close, this temp password won't show again (copy first if needed). Close?",
"admin.users.tempPwNew": "New islander temp password",
"admin.users.tempPw": "Temp password",
"admin.users.tempPwPersist": "(stays visible · survives refresh)",
"admin.users.copyPw": "Copy password",
"admin.users.close": "Close",
"admin.users.createTitle": "Add islander",
"admin.users.memberName": "Display name",
"admin.users.displayNamePh": "Display name",
"admin.users.email": "Email",
"admin.users.initPassword": "Initial password (optional)",
2026-07-10 12:54:45 +00:00
"admin.users.initPasswordPh": "Leave blank to auto-generate; if set, must meet policy",
2026-07-10 05:10:31 +00:00
"admin.users.markVerifiedCheck": "Mark email verified (usable immediately)",
"admin.users.alsoAdmin": "Also make admin",
"admin.users.creating": "Creating…",
"admin.users.createSubmit": "Create islander",
"admin.users.clear": "Clear",
"admin.users.searchActive": "Search “{query}” · matches name, email, uid",
"admin.users.noMatch": "No matches",
"admin.users.none": "No islanders yet",
"admin.users.you": "You",
"admin.users.status": "Status",
"admin.users.role": "Roles",
"admin.users.emailVerify": "Email verification",
"admin.users.bio": "Bio",
"admin.users.timezone": "Timezone",
"admin.users.notifyEmail": "Email notifications",
"admin.users.on": "On",
"admin.users.off": "Off",
"admin.users.createdAt": "Created",
"admin.users.updatedAt": "Updated",
"admin.users.accountStatus": "Account status",
"admin.users.updating": "Updating…",
"admin.users.usageTitle": "Usage & plan",
2026-07-10 12:54:45 +00:00
"admin.users.usageLiveSkip": "Plan/quota are Usage domain — not on live backend yet (M3). Editable in mock only.",
2026-07-10 05:10:31 +00:00
"admin.users.plan": "Plan",
"admin.users.planOption": "{name} ({credits} credits / mo)",
"admin.users.unlimited": "Unlimited",
"admin.users.byPlan": "By plan",
"admin.users.setUnlimited": "Set unlimited",
"admin.users.setLimited": "Enforce plan limits",
"admin.users.unlimitedHint": "Unlimited: can keep using past plan cap; AI/Search counts and credits still track.",
"admin.users.loadingUsage": "Loading usage prefs…",
"admin.users.assignRoles": "Assign roles",
"admin.users.memberBase": "{role} (base, always on)",
"admin.users.adminDesc": "{role} — manage islanders and system",
"admin.users.saving": "Saving…",
"admin.users.saveRoles": "Save roles",
"admin.users.markUnverifiedBtn": "Mark unverified",
"admin.users.markVerifiedBtn": "Mark verified",
"admin.users.resetting": "Resetting…",
"admin.users.resetTemp": "Reset password (temp)",
"admin.users.customPw": "Or set a password (optional)",
2026-07-10 12:54:45 +00:00
"admin.users.customPwPh": "Password must be at least 12 characters with upper, lower, digit, and symbol",
2026-07-10 05:10:31 +00:00
"admin.users.resetWithCustom": "Reset with this password",
"usage.tabMine": "My usage",
"usage.tabTenant": "All usage",
"usage.currentPlan": "Current plan",
"usage.planMeta": "/ mo · {n} credits monthly",
"usage.changePlan": "Change plan",
"usage.usedThisMonth": "Used this month",
"usage.remainLabel": "Remaining",
"usage.ledgerToggle": "Usage log",
"usage.collapse": "Collapse",
"usage.eventsCount": "{n} events",
"usage.granularity": "Granularity",
"usage.day": "Day",
"usage.monthUnit": "Month",
"usage.year": "Year",
"usage.from": "From",
"usage.to": "To",
"usage.callCounts": "Call counts",
"usage.noMembers": "No members yet",
"usage.planAria": "{name} plan",
"usage.unlimitedTitle": "Unlimited",
"usage.setLimited": "Enforce limits",
"usage.setUnlimited": "Set unlimited",
"usage.limitShort": "Cap",
"usage.subscribed": "Subscribed to {name}",
"usage.unlimitedSet": "Set unlimited",
"usage.limitedSet": "Limits enforced",
"usage.planUpdated": "Plan updated to {name}",
"usage.fail": "Failed",
"currency.TWD": "New Taiwan Dollar (TWD)",
"currency.USD": "US Dollar (USD)",
"currency.JPY": "Japanese Yen (JPY)",
"currency.EUR": "Euro (EUR)",
"currency.HKD": "Hong Kong Dollar (HKD)",
"locale.zh-TW": "繁體中文",
"locale.en": "English",
"pager.nav": "Pagination",
"pager.pageSize": "Items per page",
"pager.perPage": "{n}/page",
"pager.prev": "Previous",
"pager.next": "Next",
"plays.defaultTitle": "New play",
"plays.topicOnPost": "On: {snippet}",
"plays.topicOnExternal": "On: {label} · {snippet}",
"plays.externalFallback": "External post",
"persona.newName": "New persona",
"persona.previewTopic": "Looking for a café I can sit in for hours",
"persona.previewReplySample": "The one in Daan is fine but crowded",
"inspire.playTitle": "Inspired thread",
"wizard.topic.fallbackTopic": "Everyday topic",
"play.err.needLead": "Pick a lead account",
"play.err.needRoot": "Add at least one root post",
"play.err.firstMustRoot": "The first step must be the root post",
"play.err.rootMustLead": "Root post must use the lead account",
"play.err.rootEmpty": "Root post text cannot be empty",
"play.err.replyAccount": "Replies can only use lead or selected cast accounts",
"play.err.replyEmpty": "Reply text cannot be empty",
"play.err.needTarget": "Pick one of your posts, or paste a Threads link",
"play.err.needReplies": "Add at least one reply",
"play.err.needReplyAccounts": "Pick at least one reply account",
"play.err.stepAccount": "Every reply needs a usable account",
"play.err.stepEmpty": "Reply text cannot be empty",
"play.err.notFound": "Play not found",
"time.justNow": "Just now",
"time.minAgo": "{n}m ago",
"time.hourAgo": "{n}h ago",
"time.dayAgo": "{n}d ago",
"time.min": "{n} min",
"time.hour": "{n} hr",
"time.day": "{n} day",
"time.expired": "Expired {span}",
"time.remaining": "{span} left",
"time.sessionUnknown": "Session not recorded",
"time.sessionExpired": "Session expired · {absolute}",
"time.sessionSoon": "Session expiring · {relative} ({absolute})",
"time.sessionOk": "Session OK · {relative} ({absolute})",
};
const catalogs: Record<AppLocale, MessageDict> = {
"zh-TW": zhTW,
en,
};
export function getCatalog(locale: AppLocale): MessageDict {
return catalogs[locale] || zhTW;
}
export function translate(
locale: AppLocale,
key: string,
params?: Record<string, string | number>,
): string {
const dict = getCatalog(locale);
let s = dict[key] ?? zhTW[key] ?? key;
if (params) {
for (const [k, v] of Object.entries(params)) {
s = s.replace(new RegExp(`\\{${k}\\}`, "g"), String(v));
}
}
return s;
}