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

3486 lines
166 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.playbooks": "市集",
"nav.insights": "成效",
"nav.benchmark": "基準",
"nav.utm": "追蹤",
"nav.more": "更多",
"nav.moreTitle": "更多功能",
"nav.users": "島民管理",
"nav.usage": "用量與方案",
"nav.profile": "會員資料",
"nav.invite": "邀請關係",
"nav.settings": "系統設定",
"nav.logout": "登出",
"nav.navigate": "導覽",
"navGroup.workflow": "主流程",
"navGroup.accounts": "帳號品牌",
"navGroup.growth": "成長工具",
"workspace.label": "工作區",
"workspace.default": "預設",
"workspace.new": " 新增工作區",
"workspace.newPrompt": "新工作區名稱",
"common.save": "儲存",
"common.cancel": "取消",
"common.loading": "載入中…",
"common.retry": "重試",
"common.back": "返回",
"common.delete": "刪除",
"common.edit": "編輯",
"common.search": "搜尋",
"common.confirm": "確定",
"common.optional": "選填",
"common.success": "已儲存",
"common.error": "發生錯誤",
"common.yes": "是",
"common.no": "否",
// 後端 envelope codeapps/backend response + middleware
"api.err.unknown": "操作失敗,請稍後再試",
"api.err.studioValidation": "資料不符合規則,請檢查後再試",
"api.err.crawlerSession": "開發模式需先同步 Chrome Session設定頁",
"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": "不能移除或停權最後一位管理員",
"auth.unreachable": "連不上伺服器,無法確認登入狀態。請檢查網路後重試。",
"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.402001": "本月平台點數已用完,請升級方案或下月再試",
"usage.err.meterCap": "此功能本月點數已達上限,請改用其他功能或升級方案",
"usage.err.platformCapacity": "平台 AI搜尋目前忙碌或已限流。可稍後再試或到設定填入自己的 API KeyBYOK繼續使用",
"api.err.500000": "伺服器發生錯誤,請稍後再試",
"api.err.timeoutAI": "AI 回應逾時(模型思考太久)。可縮短結構備註後再試,或到設定換較快的模型",
"api.err.501000": "此功能尚未實作",
// 後端 data.message 成功文案
"api.ok.verifySent": "驗證碼已寄出,請查收信箱",
"api.ok.verifyIssued": "驗證碼已產生",
"api.ok.resetSent": "重設信已寄出,請查收信箱",
"api.ok.passwordUpdated": "密碼已更新",
"api.ok.loggedOut": "已登出",
"api.ok.unbound": "已解除綁定",
"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",
"login.liveHint": "Live 後端admin@haixun.local / admin123gateway :8888",
"forgot.title": "忘記密碼",
"forgot.submit": "寄送重設連結",
"forgot.submitting": "送出中…",
"forgot.back": "返回登入",
"forgot.hint": "輸入註冊用 Email我們會寄送重設連結與驗證碼。",
"forgot.mockMail": "重設信",
"forgot.openReset": "前往輸入驗證碼/重設密碼",
"forgot.retry": "再試一次",
"forgot.nextStep": "請查收信箱中的驗證碼或連結,再到重設頁完成新密碼。",
"reset.title": "設定新密碼",
"reset.hint": "請輸入信箱、驗證碼(信內 6 碼或連結參數)與新密碼。",
"reset.code": "驗證碼",
"reset.codePh": "信內 6 位數字",
"reset.needEmail": "請輸入 Email",
"reset.needCode": "請輸入驗證碼",
"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.loadFail": "載入設定失敗,請重新整理再試",
"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": "資料來源",
"settings.dataSourceHint":
"業務資料一律走 live API。Mock 僅保留邀請關係等少數本機模組;請維持 Live 並連 gateway。",
"settings.dataSourceMock": "Mock已縮",
"settings.dataSourceLive": "Live後端 API",
"settings.dataSourceCurrent": "目前",
"settings.dataSourceSwitchedLive": "已切到 Live — 請用後端帳號重新登入admin@haixun.local / admin123",
"settings.dataSourceSwitchedMock": "已切回 Mock邀請外仍打 live",
"settings.dataSourceLiveNeedGateway": "需 gateway 在 :8888或 Vite proxy /api",
"settings.ai": "AI",
"settings.search": "搜尋",
"settings.threads": "Threads 連帳(平台)",
"settings.threadsHint":
"App IDSecret 在 gateway 平台設定yamlenvSecret 不會顯示。請把 Callback 貼到 Meta 後台,並用 https 公開站連帳。",
"settings.threadsProvider": "目前模式",
"settings.threadsProviderFake": "Fake開發本機可測 OAuth 流程)",
"settings.threadsProviderMeta": "Meta 正式",
"settings.threadsConfigured": "App 憑證",
"settings.threadsConfiguredYes": "已設定",
"settings.threadsConfiguredNo": "未設定",
"settings.threadsCallback": "OAuth Callback URLredirect_uri",
"settings.threadsCallbackHint": "Meta App → Valid OAuth Redirect URIs 請貼這一整行(必須 https",
"settings.threadsCopy": "複製",
"settings.threadsCopied": "已複製 Callback URL",
"settings.threadsCopyFail": "複製失敗,請手動選取",
"settings.threadsPublicWeb": "公開站 origin",
"settings.threadsGoCrew": "前往 Crew 連帳",
"settings.member": "會員與登入",
"settings.usageCard": "AI搜尋額度",
"settings.usageCardHint": "平台代付點數與方案上限;自備 Key 不占平台點。",
"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.timesShort": "{n} 次",
"usage.meter.pt": "點",
"usage.meter.over": "已超出",
"usage.meter.locked": "已鎖",
"usage.meter.cap": "單項上限 {credits}/{cap} 點",
"usage.side.aiCredits": "AI 相關已用點數(文案+研究+生圖)",
"usage.side.searchCredits": "搜尋已用點數",
"usage.byok.title": "自備 Key 用量",
"usage.byok.hint": "只計呼叫次數,不占平台點數與分項進度。",
"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": "移除頭像",
"profile.avatarHint": "JPGPNGWebP5MB 內。選圖後按「儲存基本資料」寫入;「移除頭像」會立刻清除。",
"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": "請輸入目前密碼",
"profile.wrongCurrentPassword": "目前密碼不正確",
"profile.passwordUpdated": "密碼已更新",
"profile.passwordFail": "變更密碼失敗",
"profile.listJoin": "、",
"profile.tenantUid": " · tenant {tenant} · uid {uid}",
"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.rewards.summary": "邀請贈點累計 {total} · 本月 {month} /上限 {cap}",
"invite.rewards.title": "邀請回饋紀錄",
"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": "不能填自己的邀請碼",
"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.tokenRenewHint": "Token 由背景任務自動延長(約第 30 天),可在「任務」查看;無需手動刷新。",
"crew.empty": "尚無帳號",
"crew.loadFail": "載入帳號失敗",
"crew.unusable": "不可用",
"crew.expires": "到期 {time}",
"crew.lastRefresh": "上次延長 {time}",
"crew.refreshSession": "延長 token",
"crew.refreshSessionHint": "用已存授權換新 token不開授權頁失敗請「連接帳號」重授權",
"crew.session.ok": "token 有效",
"crew.session.soon": "即將到期",
"crew.session.expired": "token 已過期",
"crew.session.unknown": "未記錄到期",
"crew.connection.connected": "已連線",
"crew.connection.error": "異常",
"crew.connection.disconnected": "已斷開",
"crew.connection.unknown": "未知",
"crew.health.needsReconnect": "需重新連帳",
"crew.health.needsReconnectHint": "token 無法使用,請按「連接帳號」重新授權(不是延長 token",
"crew.health.disconnectedHint": "已解除綁定",
"crew.health.expiredHint": "請延長 token 或重新連帳",
"crew.opHealthScore": "操作 {n}",
"crew.msg.refreshed": "@{user} 已用現有授權延長 token約 60 天)",
"crew.msg.refreshedAll": "已用現有授權延長 {n} 個帳號 token",
"crew.msg.refreshFail": "延長失敗token 失效時請重新「連接帳號」)",
"crew.msg.oauthOk": "Threads 帳號已連線;已排程約 30 天後自動延長 token見任務",
"crew.msg.oauthFail": "OAuth 連線失敗",
"crew.msg.oauthUrlFail": "無法取得授權網址,請稍後再試或檢查平台 Threads 設定",
"crew.msg.deleted": "已移除 @{user}",
"crew.confirmDelete": "確定刪除帳號 @{user}\n刪除後無法再選為 lead / cast。",
"today.findTopic": "找話題",
"today.refreshTopics": "刷新話題",
"today.reload": "重新整理",
"today.loadFail": "無法載入今日資料",
"today.trendsFail": "無法刷新話題(可能額度不足或搜尋未設定)",
"today.trendsUpdated": "已更新 {n} 個話題",
"today.syncPosts": "同步已發文",
"today.syncPostsFail": "同步貼文失敗",
"today.needAccount": "請先連接 Threads 帳號",
"today.outcome.title": "本週成果",
"today.outcome.reach": "觸達",
"today.outcome.conversations": "對話",
"today.outcome.follows": "追蹤",
"today.outcome.followsHint": "可能相關,尚無強訊號",
"today.outcome.followsConfirmedHint": "/確定 {n}",
"today.outcome.conversions": "成交",
"today.outcome.emptyHint": "本週還沒有海巡外展成果,去海巡試試身手?",
"today.checkup.empty": "尚未產生本週健檢,將於下週一(依你的時區)自動產生。",
"today.checkup.prefix": "健檢:",
"today.pendingReplies": "待回覆",
"today.pendingRepliesN": "待回覆 · {n}",
"today.newThread": "寫一則",
"today.metricsAria": "今日數值",
"today.metric.pending": "待回",
"today.metric.pendingHint": "海巡佇列",
"today.metric.doneGoal": "已回/目標",
"today.metric.doneGoalHint": "今日海巡完成數/目標(海巡標記已發會累加)",
"today.metric.sentToday": "今日已發",
"today.metric.running": "進行中 {n}",
"today.metric.sentDone": "完成的發送",
"today.metric.failed": "發送異常",
"today.metric.needAction": "需處理",
"today.metric.ok": "正常",
"today.metric.mentions": "提及",
"today.metric.mentionsHint": "待回提及",
"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.badge.drafted": "已草稿",
"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.loadFail": "載入發送列表失敗",
"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.loadFail": "載入發送內容失敗",
"outbox.detail.loading": "載入中…",
"outbox.detail.sendingHint": "正在發到 Threads通常 1030 秒),頁面會自動更新…",
"outbox.detail.doneHint": "已成功發到 Threads。",
"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": "操作失敗",
"outbox.step.published": "已發佈",
"outbox.step.failed": "失敗",
"outbox.step.publishing": "發佈中…",
"outbox.step.scheduled": "排程中",
"outbox.step.blocked": "已阻擋",
"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.emptyHint": "按「從 Threads 同步」拉取別人 @ 你的貼文/回覆/引用。若權限不足請到設定重新連帳。",
"mentions.needAccount": "請先在頂部選 Threads 帳號",
"mentions.sync": "從 Threads 同步",
"mentions.syncing": "同步中…",
"mentions.syncDone": "已同步 {n} 則提及",
"mentions.syncFail": "同步失敗:請確認已連帳,且 OAuth 含 threads_manage_mentions可能需重新連帳",
"mentions.openThread": "開原文",
"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": "已將這則提及標記為已回覆",
"mentions.markReplied": "標記為已回覆",
"mentions.markingReplied": "標記中…",
"mentions.withImages": " · 附圖 {n}",
"compose.hint": "純發文:寫正文後送出 Outbox非串場。互回請用",
"compose.hintEnd": "。",
"compose.playsLink": "串場",
"compose.personaOff": "人設未 ready仿寫分析等 AI 工具停用。",
"compose.title": "標題(選填)",
"compose.titlePh": "方便在 Outbox 辨識",
"compose.body": "正文",
"compose.bodyPh": "寫下這則貼文…",
"compose.bodyCount": "{n} 字",
"compose.bodyLongWarning": "完整草稿已保留,但可能超過 Threads 單則可發布長度",
"compose.topicTag": "話題標籤Threads tag",
"compose.topicTagPh": "例如 寵物展(可不加 #",
"compose.topicTagHint": "Threads 話題標籤每則最多一個150 字,勿含 . 或 &。也可在正文寫 #標籤。",
"compose.tool.mimic": "仿寫",
"compose.tool.viral": "爆紅分析",
"compose.tool.research": "上網補資料",
"compose.tool.image": "產圖",
"compose.mimic.title": "仿寫別人貼文",
"compose.mimic.source": "參考全文",
"compose.mimic.sourcePh": "貼上想仿寫的貼文…",
"compose.mimic.direction": "新主題/新角度(可留空)",
"compose.mimic.directionPh": "例如:改寫成『功能越少,產品反而越好用』的觀點…",
"compose.mimic.directionHint": "這是新貼文真正要談的內容。留空時 AI 會從參考文延伸不同角度,不會照原文換句話說。",
"compose.mimic.structureNotes": "結構分析(會帶進仿寫)",
"compose.mimic.structureNotesPh": "可從「我的貼文 → 分析結構」帶入;或手動貼鉤子/結構/可複製點…",
"compose.mimic.structureNotesHint": "只借用敘事骨架、轉折與情緒曲線;內容依新方向重寫,語氣使用目前選擇的人設。",
"compose.mimic.broughtAnalysis": "已帶入參考貼文 + 結構分析,可直接仿寫或再改備註",
"compose.mimic.broughtSource": "已帶入參考貼文(尚未有結構分析;可先回我的貼文按「分析結構」)",
"compose.mimic.running": "仿寫中(背景任務,可離開本頁)…",
"compose.mimic.run": "依人設仿寫到正文",
"compose.mimic.queued": "已排程仿寫任務,完成後會自動填入正文",
"compose.mimic.done": "仿寫完成,可再改",
"compose.mimic.doneWithStructure": "仿寫完成(已套用結構分析骨架),可再改",
"compose.mimic.jobFail": "仿寫任務失敗:{err}",
"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": "已產圖",
"compose.scheduleAt": "預計發送時間",
"compose.scheduleHint": "到點後由 Outbox 依序送出;不可早於現在。",
"compose.scheduleHintNow": "立即發送(到點=現在,送出時以當下為準)。",
"compose.schedulePast": "預計發送時間已過期,請改為現在或未來時間。",
"compose.scheduleNow": "設為現在",
"compose.publish": "送出到 Outbox",
"compose.publishing": "送出中…",
"compose.uploadingImages": "上傳圖片 {n}/{total}…",
"compose.uploadImageFail": "圖片上傳失敗請重試或換較小的圖≤5MB",
"compose.waitImageUpload": "圖片還在上傳,請稍候再送出。",
"compose.waitImageUploadBtn": "圖片上傳中…",
"compose.imageUploadNeedRetry": "有圖片上傳失敗,請點縮圖上的重試後再送出。",
"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 同步 {n} 則貼文(含成效與留言)",
"posts.syncFail": "同步失敗,請確認已連帳且權限足夠(可能需重新 OAuth",
"posts.loadingReplies": "載入留言中…",
"posts.loadRepliesFail": "載入留言失敗",
"posts.empty": "尚無貼文",
"posts.openThreads": "開 Threads",
"posts.insight": "分析洞察:{text}",
"posts.review": "覆盤:{text}",
"posts.formulaResult": "結構分析結果",
"posts.analyzedBadge": "已分析",
"posts.noText": "(此則無文字/純媒體)",
"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.needAccount": "請選擇要送出的 Threads 帳號",
"posts.sending": "送出到 Threads 中…",
"posts.sent": "已用 @{user} 發到 Threads",
"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.quickFill": "快速填入",
"wizard.topic.sampleTitle": "週末咖啡話題",
"wizard.topic.sampleTopic": "週末想找間不踩雷的咖啡店,插座要多、能坐久。",
"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}",
"image.uploading": "上傳中",
"image.uploadingN": "正在上傳 {n} 張圖…",
"image.uploadFail": "上傳失敗",
"image.uploadBadUrl": "上傳回應無效",
"image.retry": "重試",
"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.desc": "背景任務分三區:執行中、定期排程、歷史。每頁可調筆數,不會一次拉完全部。",
"jobs.startDemo": "產生測試任務",
"jobs.demoHint": "需 worker 執行;狀態會自動輪詢更新。",
"jobs.demoLabel": "Demo 測試任務",
"jobs.demoCreated": "已建立測試任務 {id}…,等待 worker 領取",
"jobs.demoFail": "無法建立測試任務",
"jobs.template.tokenRenew": "Threads Token 定期延長(約每 30 天)",
"jobs.template.tokenRenewCadence": "約每 30 天自動執行一次 · 無需手動操作",
"jobs.template.tokenRenewBadge": "定期 · 每 30 天",
"jobs.template.personaAnalyzeAccount": "人設分析 · 爬取公開貼文",
"jobs.template.personaAnalyzeText": "人設分析 · 文字來源",
"jobs.template.composeMimic": "仿寫貼文",
"jobs.template.playGenerateScript": "劇本一次產全文",
"jobs.template.unknown": "其他任務",
"jobs.stripMore": "還有 {n} 個進行中…",
"jobs.nextRun": "下次執行:{time}",
"jobs.status.pending": "待處理",
"jobs.status.queued": "已排程",
"jobs.status.running": "執行中",
"jobs.status.succeeded": "已完成",
"jobs.status.failed": "失敗",
"jobs.status.cancelled": "已取消",
"jobs.status.cancel_requested": "取消中",
"jobs.loadFail": "無法載入任務列表",
"jobs.empty": "尚無任務",
"jobs.empty.active": "目前沒有執行中或待領取的任務",
"jobs.empty.recurring": "尚無定期/遠期排程任務",
"jobs.empty.history": "尚無歷史紀錄(已完成/失敗/取消)",
"jobs.tabsAria": "任務分類",
"jobs.tab.active": "執行中",
"jobs.tab.recurring": "定期任務",
"jobs.tab.history": "歷史已執行",
"jobs.recurringHint": "尚未到期的排程(例如 Token 約 30 天延長)。到期後會出現在「執行中」。",
"jobs.total": "共 {n} 筆",
"jobs.showing": " · 顯示前 {n}",
"jobs.detail": "詳情",
"jobs.loadMore": "載入更多(還有 {n}",
"jobs.notFound": "找不到任務",
"jobs.detailLoadFail": "載入任務失敗",
"jobs.progress": "進度 {n}%",
"jobs.updated": "更新 {time}",
"jobs.backList": "返回列表",
"jobs.backCompose": "回寫一則",
"jobs.mimicApplyCompose": "套用到寫一則",
"jobs.mimicApplyHint": "仿寫已完成。按下方按鈕回到單篇發文,正文會自動帶入。",
"jobs.mimicNoResult": "找不到仿寫結果,請再跑一次仿寫",
"jobs.mimicApplyFail": "套用失敗",
"jobs.delete": "刪除",
"jobs.deleteConfirm": "確定刪除「{name}」?此操作無法復原。",
"jobs.deleted": "已刪除任務",
"jobs.deleteFail": "無法刪除任務",
"jobs.deleteRunningHint": "執行中的任務無法刪除,請稍候完成。",
"jobs.retentionHint": "終態任務約保留 2 天後自動清除",
"plans.title": "變更方案",
"plans.current": "目前方案",
"plans.perMonth": "/月",
"plans.monthlyCredits": "每月 {n} 點",
"plans.usageLink": "用量",
"plans.inUse": "使用中",
"plans.recommended": "推薦",
"plans.creditsPerMonth": "每月 {n} 點",
"plans.manage": "管理訂閱",
"plans.loadFail": "無法載入訂閱方案",
"plan.cta.current": "目前方案",
"plan.cta.upgrade": "升級",
"plan.cta.downgrade": "降級",
"plan.cta.switch": "切換",
"plan.free.headline": "夠用試用,體驗完整流程",
"plan.free.bullet1": "每月 {n} 點(約 23 週輕度日常)",
"plan.free.bullet2": "完整功能:創作、海巡、發送、生圖",
"plan.free.bullet3": "用得出價值再升級 Starter",
"plan.free.bullet4": "平台忙碌時可改填自己的 Key",
"plan.free.right1": "可使用完整功能:帳號、創作、海巡、發送、任務與靈感。",
"plan.free.right2": "點數夠你真實試跑文案、搜尋與幾次生圖,不是空殼 demo。",
"plan.free.right3": "達上限後升級 Starter 繼續;或設定自備 KeyBYOK不占平台點。",
"plan.free.quota1": "每月配給 {n} 點。",
"plan.free.note1": "Free 使用者無需付款;付費使用者請由帳務入口管理取消。",
"plan.free.note2": "取消付費訂閱後,方案依帳務入口顯示的日期切換。",
"plan.starter.headline": "小團隊日常發文與海巡",
"plan.starter.bullet1": "每月 {n} 點(約 5× 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.note1": "需付款成功才變更方案。",
"plan.starter.note2": "自然月重置,未用完點數不累積至下月。",
"plan.pro.headline": "多帳、重度 AI 與研究",
"plan.pro.bullet1": "每月 {n} 點(約 3× Starter",
"plan.pro.bullet2": "高頻文案/研究/生圖 · 重度天花板",
"plan.pro.bullet3": "適合代理與多品牌",
"plan.pro.bullet4": "付款成功立即生效",
"plan.pro.right1": "付款成功後本帳改為 Pro當月依 Pro 額度計算。",
"plan.pro.right2": "適合多帳、大量回覆與深研究,減少中途額度見底。",
"plan.pro.right3": "功能相同;買的是容量。再高可改 BYOK平台限流時也不中斷。",
"plan.pro.quota1": "每月 {n} 點 · {price}。",
"plan.pro.note1": "付款失敗不會改方案。",
"plan.pro.note2": "付款完成後可於帳務紀錄查詢收據。",
"plan.quota2": "分項點數:文案 {copy}(約 {copyCalls} 次)、研究 {research}(約 {researchCalls} 次)、搜尋 {search}(約 {searchCalls} 次)、生圖 {image}(約 {imageCalls} 張)。",
"plan.softCapsLine": "分項點數:文案 {copy} · 研究 {research} · 搜尋 {search} · 生圖 {image}",
"plan.approxCallsLine": "約 {copyCalls} 次文案 · {researchCalls} 次研究 · {searchCalls} 次搜尋 · {imageCalls} 張圖",
"checkout.title": "確認方案",
"checkout.pickFirst": "請先選擇方案。",
"checkout.viewPlans": "看方案",
"checkout.fail": "無法完成",
"checkout.confirmFree": "確認切換至 Free",
"checkout.payAndAction": "{action}並付款 {price}",
"checkout.subscribe": "訂閱",
"checkout.perMonth": "/月",
"checkout.monthlyCredits": "每月 {n} 點",
"checkout.youGet": "你會得到",
"checkout.quota": "額度",
"checkout.notes": "注意",
"checkout.amountDue": "應付金額",
"checkout.billedMonthly": "{name} · 按月計費",
"checkout.already": "已是此方案",
"checkout.processing": "處理中…",
"checkout.currentPlan": "目前方案",
"checkout.pickOther": "改選其他方案",
"checkout.cancel": "取消",
"checkout.invalidUrl": "付款服務回傳了不安全的網址,未進行跳轉。",
"checkout.redirecting": "正在前往 Stripe 安全付款頁面…",
"checkout.redirectingPortal": "正在前往 Stripe 訂閱管理頁面…",
"checkout.redirectFailed": "無法開啟 Stripe 頁面。請檢查瀏覽器或網路設定後再試一次。",
"checkout.networkError": "無法連線至帳務服務。請檢查網路後再試一次。",
"checkout.unavailable": "帳務服務目前尚未啟用或暫時無法使用,請稍後再試。",
"checkout.sessionExpired": "登入狀態已失效,請重新登入後再試。",
"checkout.portalUnavailable": "目前沒有可管理的 Stripe 訂閱。請先選擇付費方案。",
"checkout.verifying": "正在確認付款與方案生效狀態…",
"checkout.pollFail": "無法查詢付款狀態,請重試。",
"checkout.missingId": "缺少結帳編號,無法確認付款結果。",
"checkout.terminalFail": "結帳未完成({status})。你可以重新選擇方案再試一次。",
"checkout.timeout": "付款可能仍在處理中,但方案尚未於 30 秒內生效。請重試查詢;請勿重複付款。",
"checkout.retry": "重試查詢",
"checkout.canceledTitle": "已取消結帳",
"checkout.canceledBody": "未變更方案,也未執行任何扣款操作。",
"checkout.manageInstead": "此方案異動請在帳務入口管理,避免建立重複訂閱。",
"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.usedOfCap": "{used}/{cap}",
"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} 已用 {credits} 點/上限 {cap} 點({count} 次)",
"usage.ledger.costAria": "消耗 {n} 點",
"usage.event.keyMode.platform": "平台點數",
"usage.event.keyMode.byok": "自備 Key",
"usage.event.cost.credits": "{n}",
"usage.event.cost.byok": "自備",
"usage.event.cost.byokAria": "使用自備 Key不扣平台點",
"usage.event.label.unknown": "使用紀錄",
"usage.event.label.genericAi": "AI 呼叫",
"usage.event.label.personaAnalyzeText": "人設分析 · 文字",
"usage.event.label.personaAnalyzeAccount": "人設分析 · 公開帳號",
"usage.event.label.composeMimic": "仿寫貼文",
"usage.event.label.composeViral": "爆紅分析",
"usage.event.label.personaPreview": "人設試產",
"usage.event.label.ownPostReply": "自己貼文 · 回覆草稿",
"usage.event.label.mentionReply": "提及 · 回覆草稿",
"usage.event.label.inspireChat": "靈感聊天",
"usage.event.label.researchSearch": "研究搜尋",
"usage.event.label.generateImage": "產生圖片",
"usage.event.label.search": "網頁搜尋",
"usage.event.label.aiComplete": "AI 補全",
"usage.event.source.personaAnalyzeText": "人設分析 · 文字",
"usage.event.source.personaAnalyzeAccount": "人設分析 · 公開帳號",
"usage.event.source.composeMimic": "仿寫貼文",
"usage.event.source.composeViral": "爆紅分析",
"usage.event.source.personaPreview": "人設試產",
"usage.event.source.ownPostAnalyze": "自己貼文 · 結構分析",
"usage.event.source.ownPostReply": "自己貼文 · 回覆草稿",
"usage.event.source.mentionReply": "提及 · 回覆草稿",
"usage.event.source.inspireChat": "靈感聊天",
"usage.event.source.researchSearch": "研究搜尋",
"usage.event.source.generateImage": "產生圖片",
"usage.event.source.proxySearch": "網頁搜尋",
"usage.event.source.proxyAi": "AI 補全",
"usage.chart.period": "區間",
"usage.chart.allocated": "配給",
"usage.chart.consumed": "消耗",
"usage.chart.pctTitle": "消耗佔配給比例",
"usage.chart.aria": "配給與消耗",
"usage.chart.colAria": "{label} 配給 {purchased} 消耗 {consumed}",
"settings.provider": "Provider",
"settings.model": "模型",
"settings.aiUnifiedHint": "文案、研究、延伸全部使用同一 provider 與模型。",
"settings.fetchModels": "取得模型",
"settings.fetchingModels": "讀取中…",
"settings.apiKey": "API Key",
"settings.configured": "已設定",
"settings.notConfigured": "未設定",
"settings.platformKeyOk": "可用平台 key可改填自己的",
"settings.modelsHint": "模型清單",
"settings.modelsCached": "模型清單來自快取(約 5 分鐘)",
"settings.modelsLoaded": "已取得 {provider} 模型清單",
"settings.aiSaved": "AI 設定已儲存",
"settings.searchSaved": "搜尋設定已儲存",
"settings.clearAiKey": "清除自備 AI Key",
"settings.aiKeyCleared": "自備 AI Key 已清除",
"settings.clearExaKey": "清除 Exa Key",
"settings.exaKeyCleared": "Exa Key 已清除",
"settings.searchProvider": "搜尋 Provider",
"settings.expand": "延伸策略",
"settings.exaKey": "Exa API Key",
"settings.devMode": "開發模式(爬蟲測試海巡)",
"settings.devModeHint": "開啟後測試海巡可走 Chrome 爬蟲;正式發文/留言仍走 API。請下載擴充以同步 Threads 登入態。",
"settings.ext.title": "Chrome 擴充套件",
"settings.ext.desc": "開發模式需安裝此擴充v1.2.0+),才能從 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",
"settings.ext.sessionTitle": "Chrome Session測試海巡",
"settings.ext.sessionHint": "從已登入的 Threads 分頁收集 cookies寫入巡樓爬蟲 session。正式發文仍走 API。",
"settings.ext.pageOrigin": "目前分頁:{origin}",
"settings.ext.detected": "擴充已偵測",
"settings.ext.notReady": "尚未偵測擴充",
"settings.ext.synced": "Session 已同步",
"settings.ext.notSynced": "Session 未同步",
"settings.ext.syncBtn": "從 Chrome 同步 Session",
"settings.ext.recheck": "重新偵測",
"settings.ext.syncOk": "Chrome session 已同步到巡樓爬蟲",
"settings.ext.syncFail": "Chrome session 同步失敗",
"settings.ext.needLogin": "尚未登入,請先登入巡樓後再同步。",
"settings.ext.notDetected": "找不到巡樓 Chrome 擴充(頁面 {origin})。請用 v1.2.1+chrome://extensions 重新載入 → 擴充選項填入同一網址並儲存 → 回此頁 F5。",
"settings.ext.reloadHint": "安裝或更新擴充後請重新載入擴充,再按 F5 刷新此頁。",
"settings.ext.detectSteps": "裝好了卻偵測不到?請依序:① chrome://extensions 確認「巡樓 Threads Session 同步」已啟用並按「重新載入」(需 v1.2.1)② 擴充「詳細資料/選項」把 Server URL 設成 {origin} 並儲存(彈窗按允許)③ 回此分頁硬重新整理F5。本機請勿混用 localhost 與 127.0.0.1。",
"forgot.fail": "送出失敗",
"forgot.mockHint": "正式環境會寄到信箱;此處直接給連結:",
"forgot.checkInbox": "請檢查信箱(含垃圾郵件)。",
"reset.mismatch": "兩次密碼不一致",
"reset.fail": "重設失敗",
"reset.cardTitle": "重設密碼",
"reset.redirecting": "即將前往登入頁…",
"reset.loginNow": "立即登入",
"reset.passwordPh": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
"reset.forgotLink": "重新申請重設",
"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.openThreadsReply": "開啟 Threads 留言",
"scout.markManualDone": "已留言,標記完成",
"scout.manualReplyHint": "先確認草稿,開啟 Threads 後直接在原文底下留言;草稿會嘗試自動複製。完成後回到這裡標記完成。",
"scout.openedAndCopied": "已開啟 Threads草稿也已複製貼上留言後再回來標記完成。",
"scout.openedManual": "已開啟 Threads留言完成後請回來標記完成。",
"scout.noPermalink": "這筆命中沒有可開啟的 Threads 原文連結。",
"scout.manualDone": "已標記人工留言完成 · 今日 {done}/{goal}",
"scout.manualDoneFail": "標記人工留言完成失敗",
"scout.resend": "重新送出",
"scout.sending": "發送中…",
"scout.needAccountBefore": "請先到",
"scout.needAccountAfter": "連線可用帳號。",
"scout.loadingKnowledge": "正在整理周邊知識…",
"scout.product": "產品",
"scout.queue": "命中紀錄 · {n}",
"scout.valueQueue": "痛點/產品接話 · {n}",
"scout.activityQueue": "活躍短回 · {n}",
"scout.noMatchesInQueue": "這個佇列暫無命中",
"scout.collapseQueue": "收合佇列",
"scout.expandQueue": "展開佇列",
"scout.noOtherPending": "沒有其他待回",
"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.loadFail": "海巡資料載入失敗,請重新整理後再試。",
"scout.scanQueued": "已建立海巡任務「{label}」,完成後會自動載入命中。",
"scout.workerWaiting": "海巡任務仍在等待 worker。請確認 apps/backend worker 正在執行。",
"scout.scanReady": "海巡完成,找到 {n} 則待回。",
"scout.queued": "已交由 @{who} 的 Outbox 發送佇列處理 · 今日 {done}/{goal}",
"scout.scanJob": "海巡任務",
"scout.scanInProgress": "正在掃描",
"scout.crawlerSessionRequired": "海巡爬蟲需要有效的 Chrome session。請在設定頁同步已登入 Threads 分頁的 session。",
"scout.openSettings": "開啟設定",
"scout.source": "來源:{source}",
"scout.classification": "分類:{classification}",
"scout.createdAt": "建立於 {time}",
"scout.openPermalink": "開啟原文",
"scout.draftFail": "產草稿失敗",
"scout.skipped": "已略過",
"scout.status.new": "待處理",
"scout.status.drafted": "已起草",
"scout.status.queued": "發送佇列中",
"scout.status.published": "已發送",
"scout.status.skipped": "已略過",
"scout.noDraft": "沒有可發送的草稿",
"scout.accountFallback": "帳號",
"scout.sent": "已發送(@{who})· 今日 {done}/{goal}",
"scout.sendFail": "發送失敗",
"scout.confirmDeletePost": "刪除這則命中?",
"scout.deletedPost": "已刪除這則命中",
"scout.stanceActivity": "短回 · 養活躍",
"scout.stanceProduct": "共感 · 可輕帶產品",
"scout.stanceRelation": "接話 · 建關係",
"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%",
"insights.panelHint": "依「我的貼文」同步數據聚合本月成效與近月趨勢",
"insights.lastSynced": "上次同步 {time}",
"insights.neverSynced": "尚未同步",
"insights.emptyTitle": "尚無貼文數據",
"insights.emptyDesc": "先按「同步貼文」從 Threads 拉入你的貼文與成效,再看月比圖與分析。",
"insights.syncDone": "已同步 {n} 則貼文,成效已更新",
"insights.syncFail": "同步失敗",
"insights.loadFail": "載入貼文失敗",
"insights.zeroViewsHint": "已有貼文但瀏覽多為 0可能 Insights 權限不足或尚未產出,可再按一次同步。",
"insights.postsInMonth": "{n} 則",
"insights.kpiForMonth": "{label} 指標",
"insights.topPostsOfMonth": "{label} · 表現較佳貼文",
"insights.noPostsInMonth": "{label} 尚無貼文",
"insights.pastMonthEmptyHint": "該月沒有已同步的貼文(過去月份只會自動補抓一次)。可手動同步或改選其他月。",
"insights.pastBackfillDone": "已補抓歷史貼文 {n} 則(過去月份只抓一次)",
"insights.autoRefreshDone": "本月成效已更新({n} 則)",
"insights.noDataNoAnalysis": "{label} 沒有貼文數據,不產生結論。",
"insights.noAnalysisYet": "{label} 尚無可寫的結論(需有已同步貼文)。",
"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.aiFail": "AI 產文失敗",
"plays.aiStepDone": "已產好此步,可再改",
"plays.aiNoneFilled": "沒有可產的空白步驟(或人設未就緒)",
"plays.needPersonaForStep": "此步請先選就緒人設,才能 AI 產文",
"plays.aiEmptyResult": "AI 回傳空白,請重試或換較快的模型",
"plays.saveBeforeAi": "請先「儲存方案」,再一次產全文(背景任務需要 play id",
"plays.scriptJobQueued": "已排程一次產全文(背景任務,可離開;完成後步驟會自動填上)",
"plays.scriptJobDone": "劇本產文完成,已填入各步驟(可再改)",
"plays.scriptJobDoneReload": "劇本產文完成,請重新開啟方案查看",
"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": "話題靈感",
"inspire.trendsLabel": "話題靈感",
"inspire.trendsHint": "網搜彙整,非官方熱搜 · 找靈感會扣搜尋點數",
"inspire.trendsSeed": "示意",
"inspire.topicSeed": "想寫跟「{topic}」有關的 Threads幫我發想開場與角度。",
"inspire.trendsEmpty": "點「找靈感」才會搜尋(扣點)",
"inspire.refreshConfirm": "找靈感會消耗 1 次「搜尋」點數,確定?",
"inspire.refreshOk": "已更新 {n} 則話題靈感",
"inspire.refreshFail": "找靈感失敗(點數不足或搜尋失敗)",
"inspire.refresh": "找靈感",
"inspire.clearChat": "新對話",
"inspire.clearedNewSession": "已開新對話",
"inspire.sessionsAria": "靈感對話列表",
"inspire.session": "對話",
"inspire.sessionNew": "新對話",
"inspire.newSession": "+ 新對話",
"inspire.newSessionOk": "已開新對話(舊的還在列表)",
"inspire.deleteSession": "刪除目前對話",
"inspire.deleteSessionShort": "刪除",
"inspire.confirmDeleteSession": "刪除目前對話?此則聊天會永久移除。",
"inspire.deletedSession": "已刪除,已切到其他對話",
"inspire.pinAsElement": "套用為元素",
"inspire.you": "你",
"inspire.ai": "AI",
"inspire.system": "系統",
"inspire.useDraft": "用這則寫",
"inspire.openPlay": "開串場",
"inspire.thinking": "思考中…",
"inspire.stop": "停止產生",
"inspire.stopped": "已停止產生",
"inspire.pinnedAria": "本輪參考(給 AI 看)",
"inspire.pinned": "本輪參考",
"inspire.pinnedCount": "· {n}",
"inspire.pinsLocalShort": "本次工作階段",
"inspire.pinsSessionLocal": "參考項目只套用於本次工作階段;送出訊息時會一併帶入。",
"inspire.pickRight": "右側點選=掛給 AI點名稱可插入輸入",
"inspire.unpinTitle": "取消參考",
"inspire.insertPinTitle": "插入主輸入",
"inspire.insertBrand": "聊聊「{name}」",
"inspire.insertedPin": "已插入「{name}」到輸入框",
"inspire.flowStep1": "備料/參考",
"inspire.flowStep2": "聊天發想",
"inspire.flowStep3": "用人設定稿",
"inspire.emptyTitle": "先聊清楚,再用人設定稿",
"inspire.emptyDesc": "選一條路開始。不需要先懂全部按鈕。",
"inspire.entryTopic": "從一句話開始發想",
"inspire.entryPaste": "已有草稿,直接用人設改寫",
"inspire.startTopicHint": "在下方輸入主題或想法Enter 送出",
"inspire.pasteDraftHint": "把草稿貼進「待改寫內容」,再按用人設改寫",
"inspire.needMaterialOrPaste": "沒有聊天素材時,請直接貼上要改寫的文字",
"inspire.flowOneLiner": "先聊清楚;需要資料時開啟查資料,最後一鍵整理成貼文。",
"inspire.showTopics": "找題材",
"inspire.hideTopics": "收起題材",
"inspire.showLibrary": "參考庫",
"inspire.hideLibrary": "收起庫",
"inspire.showAdvanced": "進階",
"inspire.hideAdvanced": "收起進階",
"inspire.readyToWrite": "已聊 {n} 輪,可以定稿了",
"inspire.inputAria": "跟 AI 說",
"inspire.inputPh": "想發想什麼Enter 送出 · Shift+Enter 換行",
"inspire.send": "送出",
"inspire.generate": "整理成貼文",
"inspire.generateHint": "根據整段對話、人設聲紋與高互動寫法整理成可發布正文",
"inspire.webSearch": "查資料",
"inspire.webSearchOn": "查資料:開",
"inspire.webSearchHint": "開啟後,下一則訊息會先用 Exa 查資料再交給 AI 討論",
"inspire.needConversation": "先聊一句你的想法,再整理成貼文。",
"inspire.needReadyPersona": "請先選擇已完成分析的人設。",
"inspire.generating": "改寫中…",
"inspire.generateOk": "已依人設改寫成草稿",
"inspire.materialTitle": "鎖定要寫的內容",
"inspire.materialHint": "產文只會改寫這段(可編輯),不會另起新主題。聊天負責發想,這裡負責定稿。",
"inspire.materialLabel": "待改寫內容",
"inspire.materialPh": "從對話整理出的重點、角度、想講的事…",
"inspire.rewriteNotes": "改寫指示(可選)",
"inspire.rewriteNotesPh": "例如:短一點、更口語、加問句",
"inspire.rewriteDefault": "用人設寫成 Threads 正文",
"inspire.confirmRewrite": "用人設改寫",
"inspire.needMaterial": "先聊出一些內容,或在素材框貼上要改寫的文字",
"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 正文",
"inspire.previewTitle": "本輪會送出的完整內容",
"inspire.previewPrompt": "完整 prompt人設品牌產品元素對話與送 AI 相同)",
"inspire.previewSections": "已帶入段落",
"inspire.previewPinnedCount": "套用元素 {n} 個",
"inspire.previewNoPins": "目前沒有套用元素(右側可點選)",
"inspire.runes": "字",
"inspire.copyAll": "複製全文",
"inspire.copied": "已複製完整 prompt",
"inspire.copyFail": "複製失敗",
"inspire.rawPrompt": "送給 AI 的原文(一字不差)",
"inspire.verifyHow": "怎麼確認一致:先按 ? 看 fingerprint → 不改內容直接送出 → 狀態列顯示「與預覽一致」。",
"inspire.verifyHowShort": "先輸入文字 → 按 ? → 不改內容按送出 → 應一致。對話不會整包重送:只帶前情摘要 + 最近幾則。",
"inspire.previewModeNote": "此為 mode={mode} 的實際組裝(與同 mode 送出相同)。",
"inspire.lastSentFp": "剛送出指紋",
"inspire.matchOk": "與上次送出一致 ✓",
"inspire.matchBad": "與預覽不一致輸入pin人設mode 不同)",
"inspire.matchBadShort": "≠ 上次送出 {sent}",
"inspire.fpMatch": "送出指紋 {fp} 與預覽一致",
"inspire.fpMismatch": "指紋不同:預覽 {preview} ≠ 送出 {sent}是否改過字mode",
"inspire.fpSent": "送出指紋 {fp}",
"inspire.viewSent": "看剛送出的全文",
"inspire.viewSentShort": "剛送",
"inspire.sentPrompt": "剛送出的完整 prompt",
"inspire.sentPromptNote": "後端實際丟給 AI 的 promptstream done 回傳)。",
"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.previewHint": "依目前指紋寫一則可能的主貼與回文;會嘗試用即時新聞當話題靈感(轉成這個人的口吻,不是新聞稿)。",
"persona.previewRunning": "產文中…",
"persona.previewDone": "試產完成 · 話題:{topic}{source}",
"persona.previewFail": "試產失敗,請再試一次",
"persona.previewTopicLabel": "話題靈感:{topic} · {source}",
"persona.topicNews": "即時新聞",
"persona.topicManual": "手動",
"persona.topicFallback": "生活靈感",
"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.jobQueued": "已排入背景任務 · 可離開此頁,完成後自動存檔",
"persona.jobQueuedCrawl": "已排入爬取/分析任務 · 可離開此頁,完成後自動寫入人設",
"persona.jobRunning": "背景分析中… 完成後會自動更新(也可到「任務」查看進度)",
"persona.jobDone": "背景分析完成 · 已寫入指紋/範本",
"persona.jobFailed": "背景分析失敗,請到任務頁查看錯誤或重試",
"persona.loadFail": "載入人設失敗",
"persona.openJob": "開啟任務詳情",
"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": "初始密碼(選填)",
"admin.users.initPasswordPh": "空白則自動產生;若填寫須符合密碼政策",
"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": "用量與方案",
"admin.users.usageLiveSkip": "方案/額度屬 Usage 域live 後端尚未接上M3此區僅 mock 可改。",
"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": "或指定新密碼(選填)",
"admin.users.customPwPh": "密碼須至少 12 碼,且含大寫、小寫、數字與符號",
"admin.users.resetWithCustom": "用指定密碼重設",
"usage.tabMine": "我的用量",
"usage.tabTenant": "全體用量",
"usage.currentPlan": "目前方案",
"usage.planMeta": "/月 · 每月 {n} 點額度",
"usage.changePlan": "變更方案",
"usage.upgradePlan": "升級方案",
"usage.outcome.title": "本月成果",
"usage.outcome.summary": "觸達 {reach} · 對話 {conversations} · 成交 {conversions}",
"usage.outcome.amount": "(約 ${amount}",
"usage.outcome.emptyHint": "本月還沒有可歸因的成果,去海巡或發文試試。",
"usage.warn.unlimitedOver": "本月已用 {used} 點(方案 {cap},不擋額度,仍可繼續)。",
"usage.warn.exhausted": "本月點數已用完。可升級方案或等待下月重置。",
"usage.warn.high": "本月已用 {pct}% 點數。",
"usage.warn.meterNear": "{label} 接近單項上限({credits}/{cap} 點)。",
"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": "靈感串場",
"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": "未記錄到期時間",
"time.sessionExpired": "Token 已過期 · {absolute}",
"time.sessionSoon": "即將到期 · {relative}{absolute}",
"time.sessionOk": "有效 · {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.playbooks": "Playbooks",
"nav.insights": "Insights",
"nav.benchmark": "Benchmark",
"nav.utm": "UTM",
"nav.more": "More",
"nav.moreTitle": "More",
"nav.users": "Islanders",
"nav.usage": "Usage & plans",
"nav.profile": "Profile",
"nav.invite": "Invites",
"nav.settings": "Settings",
"nav.logout": "Log out",
"nav.navigate": "Navigate",
"navGroup.workflow": "Workflow",
"navGroup.accounts": "Accounts & brands",
"navGroup.growth": "Growth tools",
"workspace.label": "Workspace",
"workspace.default": "Default",
"workspace.new": " New workspace",
"workspace.newPrompt": "New workspace name",
"common.save": "Save",
"common.cancel": "Cancel",
"common.loading": "Loading…",
"common.retry": "Retry",
"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",
"api.err.unknown": "Something went wrong. Please try again.",
"api.err.studioValidation": "Invalid data. Please check and try again.",
"api.err.crawlerSession": "Dev mode needs a Chrome session sync (Settings).",
"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",
"auth.unreachable": "Can't reach the server, so your sign-in state is unknown. Check your connection and retry.",
"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.402001": "Monthly platform credits exhausted. Upgrade or wait for next month.",
"usage.err.meterCap": "This feature hit its monthly credit cap. Try another feature or upgrade.",
"usage.err.platformCapacity": "Platform AI/search is busy or rate-limited. Try again later, or add your own API key (BYOK) in Settings.",
"api.err.500000": "Server error. Please try again later.",
"api.err.timeoutAI": "AI timed out. Shorten structure notes, or pick a faster model in Settings",
"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",
"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",
"login.liveHint": "Live backend: admin@haixun.local / admin123 (gateway :8888)",
"forgot.title": "Forgot password",
"forgot.submit": "Send reset link",
"forgot.submitting": "Sending…",
"forgot.back": "Back to sign in",
"forgot.hint": "Enter your registered email. We'll send a reset link and code.",
"forgot.mockMail": "Reset email",
"forgot.openReset": "Enter code / reset password",
"forgot.retry": "Try again",
"forgot.nextStep": "Check your email for the code or link, then open the reset page to set a new password.",
"reset.title": "Set new password",
"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",
"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.loadFail": "Could not load settings. Refresh to try again.",
"settings.localeCurrency": "Language & currency",
"settings.locale": "Interface language",
"settings.currency": "Display currency",
"settings.currencyHint": "Display only; plan billing stays in TWD.",
"settings.localeSaved": "Language and currency updated",
"settings.appearance": "Appearance",
"settings.theme": "Theme",
"settings.themeLight": "Light",
"settings.themeDark": "Dark",
"settings.themeSystem": "System",
"settings.themeHint": "Light, dark, or follow system appearance.",
"settings.themeSaved": "Theme updated",
"settings.themeToLight": "Switch to light",
"settings.themeToDark": "Switch to dark",
"settings.dataSource": "Data source",
"settings.dataSourceHint":
"Business data always uses live API. Mock keeps only a few local modules (e.g. invite). Prefer Live + gateway.",
"settings.dataSourceMock": "Mock (reduced)",
"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 (non-invite still hits live)",
"settings.dataSourceLiveNeedGateway": "Requires gateway on :8888 (or Vite proxy /api)",
"settings.ai": "AI",
"settings.search": "Search",
"settings.threads": "Threads OAuth (platform)",
"settings.threadsHint":
"App ID/Secret live in gateway platform config (yaml/env); Secret is never shown. Paste Callback into Meta app settings and connect via the public https site.",
"settings.threadsProvider": "Mode",
"settings.threadsProviderFake": "Fake (dev OAuth flow)",
"settings.threadsProviderMeta": "Meta production",
"settings.threadsConfigured": "App credentials",
"settings.threadsConfiguredYes": "Configured",
"settings.threadsConfiguredNo": "Not set",
"settings.threadsCallback": "OAuth Callback URL (redirect_uri)",
"settings.threadsCallbackHint": "Paste this exact URL into Meta App → Valid OAuth Redirect URIs (https required)",
"settings.threadsCopy": "Copy",
"settings.threadsCopied": "Callback URL copied",
"settings.threadsCopyFail": "Copy failed — select manually",
"settings.threadsPublicWeb": "Public site origin",
"settings.threadsGoCrew": "Open Crew to connect",
"settings.member": "Account & sign-in",
"settings.usageCard": "AI / search quota",
"settings.usageCardHint": "Platform credits and plan caps; BYOK does not use platform credits.",
"settings.viewUsage": "View usage",
"settings.editProfile": "Edit profile",
"settings.mockLogin": "demo@harbor.local / demo",
"settings.memberHint": "Sign-in account, display name, and notification prefs.",
"usage.title": "Usage & plans",
"usage.desc": "See platform credits this month, per-feature usage, and change plans.",
"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": "After you create, patrol, or generate images, usage events show up here.",
"usage.planNote": "Resets each calendar month; unused credits do not roll over.",
"usage.switched": "Switched to {name}",
"usage.meter.times": "{count} runs · {credits} credits",
"usage.meter.timesShort": "{n} runs",
"usage.meter.pt": "pt",
"usage.meter.over": "over",
"usage.meter.locked": "locked",
"usage.meter.cap": "Cap {credits}/{cap} credits",
"usage.side.aiCredits": "AI credits used (copy + research + image)",
"usage.side.searchCredits": "Search credits used",
"usage.byok.title": "BYOK usage",
"usage.byok.hint": "Calls only; does not affect platform credits or progress bars.",
"usage.plan.free.blurb": "Enough to try the full creation flow",
"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": "Manage display name, avatar, and password.",
"profile.accountStatus": "Account status",
"profile.basic": "Basics",
"profile.avatar": "Avatar",
"profile.avatarUpload": "Upload avatar",
"profile.avatarRemove": "Remove avatar",
"profile.avatarHint": "JPG / PNG / WebP, up to 5MB. Pick a file then Save basic info; Remove clears immediately.",
"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",
"profile.wrongCurrentPassword": "Current password is incorrect",
"profile.passwordUpdated": "Password updated",
"profile.passwordFail": "Could not change password",
"profile.listJoin": ", ",
"profile.tenantUid": " · tenant {tenant} · uid {uid}",
"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.rewards.summary": "Reward points total {total} · this month {month} / cap {cap}",
"invite.rewards.title": "Reward history",
"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",
"admin.users.title": "Islanders",
"admin.users.desc": "Manage islander accounts, roles, plans, and unlimited flags.",
"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": "Connecting…",
"crew.tokenRenewHint": "Tokens auto-renew via background jobs (~day 30). Check Jobs; no manual refresh.",
"crew.empty": "No accounts yet",
"crew.loadFail": "Could not load accounts",
"crew.unusable": "Unavailable",
"crew.expires": "Expires {time}",
"crew.lastRefresh": "Last extended {time}",
"crew.refreshSession": "Extend token",
"crew.refreshSessionHint": "Uses stored auth to refresh the token — no OAuth page. On failure, reconnect.",
"crew.session.ok": "Token valid",
"crew.session.soon": "Expiring soon",
"crew.session.expired": "Token expired",
"crew.session.unknown": "Expiry unknown",
"crew.connection.connected": "Connected",
"crew.connection.error": "Error",
"crew.connection.disconnected": "Disconnected",
"crew.connection.unknown": "Unknown",
"crew.health.needsReconnect": "Reconnect required",
"crew.health.needsReconnectHint": "Token unusable — use Connect account (not Extend token)",
"crew.health.disconnectedHint": "Unlinked",
"crew.health.expiredHint": "Extend token or reconnect",
"crew.opHealthScore": "Health {n}",
"crew.msg.refreshed": "@{user} token extended with stored auth (~60 days)",
"crew.msg.refreshedAll": "Extended {n} account tokens with stored auth",
"crew.msg.refreshFail": "Extend failed (reconnect if token is invalid)",
"crew.msg.oauthOk": "Threads connected; token renew scheduled ~day 30 (see Jobs)",
"crew.msg.oauthFail": "OAuth connection failed",
"crew.msg.oauthUrlFail": "Could not get authorize URL. Try again or check platform Threads settings.",
"crew.msg.deleted": "Removed @{user}",
"crew.confirmDelete": "Delete account @{user}?\nIt can no longer be used as lead / cast.",
"today.findTopic": "Find topics",
"today.refreshTopics": "Refresh topics",
"today.reload": "Reload",
"today.loadFail": "Could not load Today",
"today.trendsFail": "Could not refresh topics (quota or search not set)",
"today.trendsUpdated": "Updated {n} topics",
"today.syncPosts": "Sync own posts",
"today.syncPostsFail": "Could not sync posts",
"today.needAccount": "Connect a Threads account first",
"today.outcome.title": "This week's outcomes",
"today.outcome.reach": "Reach",
"today.outcome.conversations": "Conversations",
"today.outcome.follows": "Follows",
"today.outcome.followsHint": "Possibly related, no strong signal yet",
"today.outcome.followsConfirmedHint": " / confirmed {n}",
"today.outcome.conversions": "Conversions",
"today.outcome.emptyHint": "No patrol outreach outcomes this week yet — go give patrol a try?",
"today.checkup.empty": "This week's checkup hasn't been generated yet. It runs automatically next Monday in your timezone.",
"today.checkup.prefix": "Checkup: ",
"today.pendingReplies": "Pending replies",
"today.pendingRepliesN": "Pending · {n}",
"today.newThread": "Compose",
"today.metricsAria": "Today metrics",
"today.metric.pending": "Pending",
"today.metric.pendingHint": "Patrol queue",
"today.metric.doneGoal": "Done / goal",
"today.metric.doneGoalHint": "Patrol completions today / goal (mark published counts)",
"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.metric.mentions": "Mentions",
"today.metric.mentionsHint": "Pending mentions",
"today.pending.title": "Patrol pending · {n}",
"today.pending.empty": "Nothing pending — run a patrol",
"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 — tap Refresh topics",
"today.goStudio": "Open inspire",
"today.heat": "Heat {n}",
"today.topicAngle": "Good opening angle",
"today.moreInspire": "More inspiration",
"today.useTopic": "Brainstorm 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.badge.drafted": "Drafted",
"today.openOutbox": "Open outbox",
"today.accounts.title": "Account performance",
"today.accounts.empty": "No stats yet — sync own posts",
"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.loadFail": "Failed to load outbox",
"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.loadFail": "Could not load this outbox item",
"outbox.detail.loading": "Loading…",
"outbox.detail.sendingHint": "Publishing to Threads (often 1030s). This page updates automatically…",
"outbox.detail.doneHint": "Published to Threads successfully.",
"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",
"outbox.step.published": "Published",
"outbox.step.failed": "Failed",
"outbox.step.publishing": "Publishing…",
"outbox.step.scheduled": "Scheduled",
"outbox.step.blocked": "Blocked",
"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.emptyHint": "Click “Sync from Threads” to pull posts/replies/quotes that @ you. Re-connect if missing threads_manage_mentions.",
"mentions.needAccount": "Select a Threads account in the top bar first",
"mentions.sync": "Sync from Threads",
"mentions.syncing": "Syncing…",
"mentions.syncDone": "Synced {n} mentions",
"mentions.syncFail": "Sync failed — reconnect Threads with threads_manage_mentions scope",
"mentions.openThread": "Open post",
"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": "Mention marked as replied",
"mentions.markReplied": "Mark as replied",
"mentions.markingReplied": "Marking…",
"mentions.withImages": " · {n} images",
"compose.hint": "Publish only: write body and send to Outbox (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.bodyCount": "{n} characters",
"compose.bodyLongWarning": "The full draft is preserved, but it may exceed the Threads single-post limit",
"compose.topicTag": "Topic tag (Threads)",
"compose.topicTagPh": "e.g. petshow (optional #)",
"compose.topicTagHint": "One topic tag per post, 150 chars, no . or &. You can also put #tag in the body.",
"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.direction": "New topic or angle (optional)",
"compose.mimic.directionPh": "e.g. Fewer features can make a product easier to use…",
"compose.mimic.directionHint": "This drives the new post. Leave it blank and AI will choose a related but distinctly different angle.",
"compose.mimic.structureNotes": "Structure notes (used in mimic)",
"compose.mimic.structureNotesPh": "From Own posts → Analyze, or paste hooks/structure…",
"compose.mimic.structureNotesHint": "Only the narrative skeleton, turns, and emotional arc are reused; content follows the new direction and selected persona.",
"compose.mimic.broughtAnalysis": "Loaded source + structure analysis — mimic or edit notes",
"compose.mimic.broughtSource": "Loaded source (no structure yet — analyze on Own posts first)",
"compose.mimic.running": "Mimicking in background (you can leave)…",
"compose.mimic.run": "Mimic into body",
"compose.mimic.queued": "Mimic job queued — will fill the body when done",
"compose.mimic.done": "Mimic done — edit as needed",
"compose.mimic.doneWithStructure": "Mimic done (structure applied) — edit as needed",
"compose.mimic.jobFail": "Mimic job failed: {err}",
"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",
"compose.scheduleAt": "Publish at",
"compose.scheduleHint": "Outbox sends at this time; must not be in the past.",
"compose.scheduleHintNow": "Send immediately (timestamp taken at submit).",
"compose.schedulePast": "Scheduled time is in the past. Set to now or a future time.",
"compose.scheduleNow": "Now",
"compose.publish": "Send to Outbox",
"compose.publishing": "Sending…",
"compose.uploadingImages": "Uploading image {n}/{total}…",
"compose.uploadImageFail": "Image upload failed — retry or use a smaller file (≤5MB)",
"compose.waitImageUpload": "Images still uploading — wait a moment.",
"compose.waitImageUploadBtn": "Uploading images…",
"compose.imageUploadNeedRetry": "Some images failed — tap retry on the thumbnail.",
"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 {n} posts from Threads (metrics + replies)",
"posts.syncFail": "Sync failed — reconnect Threads if permissions are missing",
"posts.loadingReplies": "Loading replies…",
"posts.loadRepliesFail": "Could not load replies",
"posts.empty": "No posts yet",
"posts.openThreads": "Open Threads",
"posts.insight": "Insight: {text}",
"posts.review": "Review: {text}",
"posts.formulaResult": "Structure analysis",
"posts.analyzedBadge": "Analyzed",
"posts.noText": "(No text / media-only)",
"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.needAccount": "Pick a Threads account to send",
"posts.sending": "Publishing to Threads…",
"posts.sent": "Sent to Threads 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.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.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; backend adds random jitter so timing is less robotic",
"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})",
"image.uploading": "Uploading",
"image.uploadingN": "Uploading {n} image(s)…",
"image.uploadFail": "Upload failed",
"image.uploadBadUrl": "Invalid upload response",
"image.retry": "Retry",
"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.desc": "Jobs in three tabs: active, scheduled, and history. Paginated so we never load everything at once.",
"jobs.startDemo": "Create test job",
"jobs.demoHint": "Requires worker; list auto-refreshes while jobs are active.",
"jobs.demoLabel": "Demo test job",
"jobs.demoCreated": "Test job {id}… created — waiting for worker",
"jobs.demoFail": "Could not create test job",
"jobs.template.tokenRenew": "Threads token renew (~every 30 days)",
"jobs.template.tokenRenewCadence": "Runs about every 30 days · no manual action needed",
"jobs.template.tokenRenewBadge": "Recurring · every 30 days",
"jobs.template.personaAnalyzeAccount": "Persona analyze · crawl public posts",
"jobs.template.personaAnalyzeText": "Persona analyze · from text",
"jobs.template.composeMimic": "Mimic post",
"jobs.template.playGenerateScript": "Play full-script AI",
"jobs.template.unknown": "Other job",
"jobs.stripMore": "+{n} more running…",
"jobs.nextRun": "Next run: {time}",
"jobs.status.pending": "Pending",
"jobs.status.queued": "Scheduled",
"jobs.status.running": "Running",
"jobs.status.succeeded": "Succeeded",
"jobs.status.failed": "Failed",
"jobs.status.cancelled": "Cancelled",
"jobs.status.cancel_requested": "Cancel requested",
"jobs.loadFail": "Could not load jobs",
"jobs.empty": "No jobs yet",
"jobs.empty.active": "No running or ready-to-claim jobs",
"jobs.empty.recurring": "No scheduled / recurring jobs yet",
"jobs.empty.history": "No history yet (succeeded / failed / cancelled)",
"jobs.tabsAria": "Job categories",
"jobs.tab.active": "Active",
"jobs.tab.recurring": "Scheduled",
"jobs.tab.history": "History",
"jobs.recurringHint": "Future schedules (e.g. token renew in ~30 days). When due, they appear under Active.",
"jobs.total": "{n} total",
"jobs.showing": " · showing first {n}",
"jobs.detail": "Details",
"jobs.loadMore": "Load more ({n} more)",
"jobs.notFound": "Job not found",
"jobs.detailLoadFail": "Could not load this job",
"jobs.progress": "Progress {n}%",
"jobs.updated": "Updated {time}",
"jobs.backList": "Back to list",
"jobs.backCompose": "Back to compose",
"jobs.mimicApplyCompose": "Apply to compose",
"jobs.mimicApplyHint": "Mimic finished. Use the button below to return to single-post compose with the draft filled in.",
"jobs.mimicNoResult": "No mimic result found — run mimic again",
"jobs.mimicApplyFail": "Could not apply result",
"jobs.delete": "Delete",
"jobs.deleteConfirm": "Delete “{name}”? This cannot be undone.",
"jobs.deleted": "Job deleted",
"jobs.deleteFail": "Could not delete job",
"jobs.deleteRunningHint": "Running jobs cannot be deleted. Wait until they finish.",
"jobs.retentionHint": "Terminal jobs are auto-removed after about 2 days",
"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",
"plans.manage": "Manage subscription",
"plans.loadFail": "Could not load your subscription",
"plan.cta.current": "Current plan",
"plan.cta.upgrade": "Upgrade",
"plan.cta.downgrade": "Downgrade",
"plan.cta.switch": "Switch",
"plan.free.headline": "Enough to try the full product",
"plan.free.bullet1": "{n} credits / month (~23 weeks light use)",
"plan.free.bullet2": "Full product: Studio, Patrol, Outbox, images",
"plan.free.bullet3": "Feel the value, then upgrade to Starter",
"plan.free.bullet4": "When platform is busy, add your own key",
"plan.free.right1": "Full access to accounts, Studio, Patrol, Outbox, jobs, and inspiration.",
"plan.free.right2": "Enough credits for real copy, search, and a few images—not a hollow demo.",
"plan.free.right3": "After the cap, upgrade to Starter—or set BYOK so you don't use platform credits.",
"plan.free.quota1": "{n} credits allocated each month.",
"plan.free.note1": "Free requires no payment; paid subscribers manage cancellation in the billing portal.",
"plan.free.note2": "After cancellation, the plan changes on the date shown in the billing portal.",
"plan.starter.headline": "Small teams posting and patrolling daily",
"plan.starter.bullet1": "{n} credits / month (about 5× Free)",
"plan.starter.bullet2": "Steady posting, replies, and patrol",
"plan.starter.bullet3": "Fits a 13 person cadence · main paid tier",
"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. Best starting paid plan.",
"plan.starter.quota1": "{n} credits / month · {price}.",
"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 3× Starter)",
"plan.pro.bullet2": "High-volume copy, research, and images · heavy ceiling",
"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. Beyond this, use BYOK—still works when platform is limited.",
"plan.pro.quota1": "{n} credits / month · {price}.",
"plan.pro.note1": "Failed payment does not change your plan.",
"plan.pro.note2": "After payment you can find receipts in billing history.",
"plan.quota2": "Per-feature credits: copy {copy} (~{copyCalls} uses), research {research} (~{researchCalls}), search {search} (~{searchCalls}), image {image} (~{imageCalls} images).",
"plan.softCapsLine": "Credits: copy {copy} · research {research} · search {search} · image {image}",
"plan.approxCallsLine": "About {copyCalls} copy · {researchCalls} research · {searchCalls} search · {imageCalls} images",
"checkout.title": "Confirm plan",
"checkout.pickFirst": "Please choose a plan first.",
"checkout.viewPlans": "View plans",
"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.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",
"checkout.invalidUrl": "The billing service returned an unsafe URL. No redirect was made.",
"checkout.redirecting": "Taking you to Stripe's secure checkout…",
"checkout.redirectingPortal": "Taking you to the Stripe subscription portal…",
"checkout.redirectFailed": "Stripe could not be opened. Check your browser or network settings and try again.",
"checkout.networkError": "Could not connect to the billing service. Check your network and try again.",
"checkout.unavailable": "Billing is not enabled or is temporarily unavailable. Please try again later.",
"checkout.sessionExpired": "Your session has expired. Sign in again and retry.",
"checkout.portalUnavailable": "There is no Stripe subscription to manage yet. Choose a paid plan first.",
"checkout.verifying": "Confirming payment and plan activation…",
"checkout.pollFail": "Could not check the payment status. Please retry.",
"checkout.missingId": "The checkout ID is missing, so the payment result cannot be verified.",
"checkout.terminalFail": "Checkout did not complete ({status}). Choose a plan and try again.",
"checkout.timeout": "Payment may still be processing, but the plan was not activated within 30 seconds. Retry the status check; do not pay again.",
"checkout.retry": "Retry status check",
"checkout.canceledTitle": "Checkout canceled",
"checkout.canceledBody": "Your plan was not changed and no payment action was performed.",
"checkout.manageInstead": "Manage this change in the billing portal to avoid a duplicate subscription.",
"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.usedOfCap": "{used}/{cap}",
"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} {credits}/{cap} credits ({count} runs)",
"usage.ledger.costAria": "Used {n} credits",
"usage.event.keyMode.platform": "Platform credits",
"usage.event.keyMode.byok": "Your own key",
"usage.event.cost.credits": "{n}",
"usage.event.cost.byok": "BYOK",
"usage.event.cost.byokAria": "Own key — no platform credits charged",
"usage.event.label.unknown": "Usage",
"usage.event.label.genericAi": "AI call",
"usage.event.label.personaAnalyzeText": "Persona analyze · text",
"usage.event.label.personaAnalyzeAccount": "Persona analyze · account",
"usage.event.label.composeMimic": "Mimic post",
"usage.event.label.composeViral": "Viral analysis",
"usage.event.label.personaPreview": "Persona preview",
"usage.event.label.ownPostReply": "Own post · reply draft",
"usage.event.label.mentionReply": "Mention · reply draft",
"usage.event.label.inspireChat": "Inspire chat",
"usage.event.label.researchSearch": "Research search",
"usage.event.label.generateImage": "Generate image",
"usage.event.label.search": "Web search",
"usage.event.label.aiComplete": "AI complete",
"usage.event.source.personaAnalyzeText": "Persona analyze · text",
"usage.event.source.personaAnalyzeAccount": "Persona analyze · account",
"usage.event.source.composeMimic": "Mimic post",
"usage.event.source.composeViral": "Viral analysis",
"usage.event.source.personaPreview": "Persona preview",
"usage.event.source.ownPostAnalyze": "Own post · structure analysis",
"usage.event.source.ownPostReply": "Own post · reply draft",
"usage.event.source.mentionReply": "Mention · reply draft",
"usage.event.source.inspireChat": "Inspire chat",
"usage.event.source.researchSearch": "Research search",
"usage.event.source.generateImage": "Generate image",
"usage.event.source.proxySearch": "Web search",
"usage.event.source.proxyAi": "AI complete",
"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}",
"settings.provider": "Provider",
"settings.model": "Model",
"settings.aiUnifiedHint": "Copy, research, and expand all share one provider and model.",
"settings.fetchModels": "Fetch models",
"settings.fetchingModels": "Loading…",
"settings.apiKey": "API key",
"settings.configured": "Configured",
"settings.notConfigured": "Not set",
"settings.platformKeyOk": "Platform key available (optional override)",
"settings.modelsHint": "Models",
"settings.modelsCached": "Models from cache (~5 min)",
"settings.modelsLoaded": "Loaded models for {provider}",
"settings.aiSaved": "AI settings saved",
"settings.searchSaved": "Search settings saved",
"settings.clearAiKey": "Clear personal AI key",
"settings.aiKeyCleared": "Personal AI key cleared",
"settings.clearExaKey": "Clear Exa key",
"settings.exaKeyCleared": "Exa key cleared",
"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 (v1.2.0+) 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": "Load unpacked (or click Reload if already installed)",
"settings.ext.step4": "Set this sites URL in extension options (must match address bar), then refresh Lapras",
"settings.ext.download": "Download extension (ZIP)",
"settings.ext.sessionTitle": "Chrome session (test patrol)",
"settings.ext.sessionHint": "Collect cookies from a logged-in Threads tab into the crawler session. Live publish still uses the API.",
"settings.ext.pageOrigin": "This tab: {origin}",
"settings.ext.detected": "Extension detected",
"settings.ext.notReady": "Extension not detected",
"settings.ext.synced": "Session synced",
"settings.ext.notSynced": "Session not synced",
"settings.ext.syncBtn": "Sync session from Chrome",
"settings.ext.recheck": "Recheck",
"settings.ext.syncOk": "Chrome session synced to crawler",
"settings.ext.syncFail": "Chrome session sync failed",
"settings.ext.needLogin": "Please sign in to Lapras before syncing.",
"settings.ext.notDetected": "Chrome extension not found on {origin}. Use v1.2.1+: reload in chrome://extensions → set Options Server URL to the same origin and Save → F5 this tab.",
"settings.ext.reloadHint": "After install/update, reload the extension and press F5 on this page.",
"settings.ext.detectSteps": "Installed but not detected? ① chrome://extensions → enable and Reload (v1.2.1+) ② Extension Options → set Server URL to {origin} and Save (Allow) ③ Hard-refresh this tab (F5). Do not mix localhost and 127.0.0.1.",
"forgot.fail": "Request failed",
"forgot.mockHint": "In production this goes to email; here is a direct link:",
"forgot.checkInbox": "Please check your inbox (and spam).",
"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",
"reset.passwordPh": "Password must be at least 12 characters with upper, lower, digit, and symbol",
"reset.forgotLink": "Request a new reset",
"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.openThreadsReply": "Open Threads to reply",
"scout.markManualDone": "Replied, mark complete",
"scout.manualReplyHint": "Review the draft, open the original Threads post, and reply there. The draft will be copied when possible. Return here to mark it complete.",
"scout.openedAndCopied": "Threads opened and the draft was copied. Paste the reply, then return to mark it complete.",
"scout.openedManual": "Threads opened. Return here after replying to mark it complete.",
"scout.noPermalink": "This result has no Threads permalink to open.",
"scout.manualDone": "Manual reply marked complete · today {done}/{goal}",
"scout.manualDoneFail": "Failed to mark the manual reply complete",
"scout.resend": "Resend",
"scout.sending": "Sending…",
"scout.needAccountBefore": "Connect a usable account under",
"scout.needAccountAfter": "first.",
"scout.loadingKnowledge": "Preparing related knowledge…",
"scout.product": "Product",
"scout.queue": "Matches · {n}",
"scout.valueQueue": "Value replies · {n}",
"scout.activityQueue": "Activity short replies · {n}",
"scout.noMatchesInQueue": "No matches in this queue",
"scout.collapseQueue": "Collapse queue",
"scout.expandQueue": "Expand queue",
"scout.noOtherPending": "No other pending",
"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.loadFail": "Scout data could not be loaded. Refresh and try again.",
"scout.scanQueued": "Patrol job “{label}” queued. Matches will load automatically when it completes.",
"scout.workerWaiting": "The patrol job is still waiting for a worker. Check that apps/backend worker is running.",
"scout.scanReady": "Patrol complete. Found {n} pending replies.",
"scout.queued": "Queued in @{who}'s Outbox for delivery · today {done}/{goal}",
"scout.scanJob": "Patrol job",
"scout.scanInProgress": "Scanning",
"scout.crawlerSessionRequired": "The patrol crawler needs a valid Chrome session. Sync the session from a signed-in Threads tab in Settings.",
"scout.openSettings": "Open Settings",
"scout.source": "Source: {source}",
"scout.classification": "Class: {classification}",
"scout.createdAt": "Created {time}",
"scout.openPermalink": "Open original",
"scout.draftFail": "Draft failed",
"scout.skipped": "Skipped",
"scout.status.new": "To handle",
"scout.status.drafted": "Drafted",
"scout.status.queued": "Queued",
"scout.status.published": "Sent",
"scout.status.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.deletedPost": "Deleted this hit",
"scout.stanceActivity": "Short reply · activity",
"scout.stanceProduct": "Empathy · soft product",
"scout.stanceRelation": "Engage · build rapport",
"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%",
"insights.panelHint": "Aggregates metrics from synced “My posts”",
"insights.lastSynced": "Last sync {time}",
"insights.neverSynced": "Not synced yet",
"insights.emptyTitle": "No post data yet",
"insights.emptyDesc": "Tap “Sync posts” to pull your Threads posts and insights, then review charts and analysis.",
"insights.syncDone": "Synced {n} posts · insights updated",
"insights.syncFail": "Sync failed",
"insights.loadFail": "Failed to load posts",
"insights.zeroViewsHint": "Posts found but views are mostly 0 — Insights scope may be missing, or stats not ready. Try sync again.",
"insights.postsInMonth": "{n} posts",
"insights.kpiForMonth": "{label} metrics",
"insights.topPostsOfMonth": "{label} · top posts",
"insights.noPostsInMonth": "No posts in {label}",
"insights.pastMonthEmptyHint": "No synced posts for this month (past months are fetched once). Sync manually or pick another month.",
"insights.pastBackfillDone": "Backfilled {n} posts (past months fetch once)",
"insights.autoRefreshDone": "Current month refreshed ({n} posts)",
"insights.noDataNoAnalysis": "No posts in {label} — no analysis.",
"insights.noAnalysisYet": "No analysis for {label} yet (need synced posts).",
"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.aiFail": "AI generate failed",
"plays.aiStepDone": "Step filled — edit as needed",
"plays.aiNoneFilled": "No empty steps to fill (or persona not ready)",
"plays.needPersonaForStep": "Pick a ready persona on this step first",
"plays.aiEmptyResult": "AI returned empty — retry or pick a faster model",
"plays.saveBeforeAi": "Save the play first, then generate the full script (needs play id)",
"plays.scriptJobQueued": "Full-script job queued — you can leave; steps fill when done",
"plays.scriptJobDone": "Script generated — steps filled (edit as needed)",
"plays.scriptJobDoneReload": "Script done — reopen the play to see steps",
"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": "Topic ideas",
"inspire.trendsLabel": "Topic ideas",
"inspire.trendsHint": "Web-sourced ideas · costs a search credit",
"inspire.trendsSeed": "sample",
"inspire.topicSeed": "I want a Threads post about “{topic}”. Help me with openings and angles.",
"inspire.trendsEmpty": "Tap “Find ideas” to search (uses credits)",
"inspire.refreshConfirm": "Finding ideas costs 1 search credit. Continue?",
"inspire.refreshOk": "Updated {n} topic ideas",
"inspire.refreshFail": "Could not find ideas (quota or search failed)",
"inspire.refresh": "Find ideas",
"inspire.clearChat": "New chat",
"inspire.clearedNewSession": "New chat started",
"inspire.sessionsAria": "Inspiration chats",
"inspire.session": "Chat",
"inspire.sessionNew": "New chat",
"inspire.newSession": "+ New",
"inspire.newSessionOk": "New chat started (previous kept in list)",
"inspire.deleteSession": "Delete current chat",
"inspire.deleteSessionShort": "Delete",
"inspire.confirmDeleteSession": "Delete this chat permanently?",
"inspire.deletedSession": "Deleted — switched to another 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.thinking": "Thinking…",
"inspire.stop": "Stop generating",
"inspire.stopped": "Generation stopped",
"inspire.pinnedAria": "This-round references (for the AI)",
"inspire.pinned": "References",
"inspire.pinnedCount": "· {n}",
"inspire.pinsLocalShort": "this session",
"inspire.pinsSessionLocal": "References apply to this session only and will be included with your next message.",
"inspire.pickRight": "Pick on the right = pin for AI; click name to insert",
"inspire.unpinTitle": "Remove reference",
"inspire.insertPinTitle": "Insert into input",
"inspire.insertBrand": "Talk about “{name}”",
"inspire.insertedPin": "Inserted “{name}” into the input",
"inspire.flowStep1": "Prep",
"inspire.flowStep2": "Ideate",
"inspire.flowStep3": "Persona draft",
"inspire.emptyTitle": "Ideate first, then draft in persona",
"inspire.emptyDesc": "Pick a path. You dont need every control.",
"inspire.entryTopic": "Start from a topic",
"inspire.entryPaste": "I have a draft — rewrite in persona",
"inspire.startTopicHint": "Type a topic below and press Enter",
"inspire.pasteDraftHint": "Paste your draft into the box, then rewrite",
"inspire.needMaterialOrPaste": "No chat material yet — paste text to rewrite",
"inspire.flowOneLiner": "Talk it through, search when needed, then turn the conversation into a post.",
"inspire.showTopics": "Topics",
"inspire.hideTopics": "Hide topics",
"inspire.showLibrary": "Library",
"inspire.hideLibrary": "Hide library",
"inspire.showAdvanced": "Advanced",
"inspire.hideAdvanced": "Hide advanced",
"inspire.readyToWrite": "{n} turns in — ready to draft",
"inspire.inputAria": "Talk to AI",
"inspire.inputPh": "What to explore? Enter to send · Shift+Enter newline",
"inspire.previewTitle": "Full payload that will be sent",
"inspire.previewPrompt": "Full prompt (persona / brands / pins / chat — same as AI)",
"inspire.previewSections": "Included sections",
"inspire.previewPinnedCount": "{n} pinned elements",
"inspire.previewNoPins": "No pinned elements yet",
"inspire.runes": "chars",
"inspire.copyAll": "Copy all",
"inspire.copied": "Full prompt copied",
"inspire.copyFail": "Copy failed",
"inspire.rawPrompt": "Raw text sent to AI",
"inspire.verifyHow": "To verify: open ? for fingerprint → send without changes → status says match.",
"inspire.verifyHowShort": "Type → ? (previews Send path) → send unchanged → should match. Generate uses different mode (fingerprint will differ).",
"inspire.previewModeNote": "Assembled for mode={mode} (same as sending with that mode).",
"inspire.lastSentFp": "Last sent fingerprint",
"inspire.matchOk": "Matches last send ✓",
"inspire.matchBad": "Differs from preview (input/pins/persona/mode)",
"inspire.matchBadShort": "≠ last sent {sent}",
"inspire.fpMatch": "Sent fingerprint {fp} matches preview",
"inspire.fpMismatch": "Different: preview {preview} ≠ sent {sent} (text/mode changed?)",
"inspire.fpSent": "Sent fingerprint {fp}",
"inspire.viewSent": "View sent prompt",
"inspire.viewSentShort": "Sent",
"inspire.sentPrompt": "Prompt actually sent",
"inspire.sentPromptNote": "Exact prompt the backend sent to the AI (from stream done).",
"inspire.send": "Send",
"inspire.generate": "Turn into post",
"inspire.generateHint": "Turn the whole conversation into a publish-ready post using the selected persona and strong engagement principles",
"inspire.webSearch": "Search web",
"inspire.webSearchOn": "Web search: on",
"inspire.webSearchHint": "The next message will search Exa before AI responds",
"inspire.needConversation": "Share one thought first, then turn it into a post.",
"inspire.needReadyPersona": "Select a persona that has finished analysis first.",
"inspire.generating": "Rewriting…",
"inspire.generateOk": "Draft rewritten in persona",
"inspire.materialTitle": "Lock content to write",
"inspire.materialHint": "Generate only rewrites this block (editable). Chat is for ideation; this is for the final voice.",
"inspire.materialLabel": "Content to rewrite",
"inspire.materialPh": "Key points, angle, what you want to say…",
"inspire.rewriteNotes": "Rewrite notes (optional)",
"inspire.rewriteNotesPh": "e.g. shorter, more casual, end with a question",
"inspire.rewriteDefault": "Rewrite as a Threads post in persona voice",
"inspire.confirmRewrite": "Rewrite in persona",
"inspire.needMaterial": "Chat a bit first, or paste text to rewrite",
"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 what you want to explore",
"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": "Start a new chat? (previous chats stay in the list)",
"inspire.genMessage": "Rewrite as a Threads post in persona voice",
"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.previewHint": "Write a sample root post and reply in this fingerprint style. Uses a live news headline as inspiration (rewritten in-character, not a news dump).",
"persona.previewRunning": "Generating…",
"persona.previewDone": "Preview done · topic: {topic} ({source})",
"persona.previewFail": "Preview failed — try again",
"persona.previewTopicLabel": "Topic seed: {topic} · {source}",
"persona.topicNews": "live news",
"persona.topicManual": "manual",
"persona.topicFallback": "everyday seed",
"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.jobQueued": "Queued as a background job · you can leave; results save automatically",
"persona.jobQueuedCrawl": "Crawl + analyze job queued · you can leave; persona updates when done",
"persona.jobRunning": "Analyzing in background… will refresh when ready (see Jobs for progress)",
"persona.jobDone": "Background analysis finished · fingerprint saved",
"persona.jobFailed": "Background analysis failed — check Jobs for the error or retry",
"persona.loadFail": "Could not load personas",
"persona.openJob": "Open job details",
"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)",
"admin.users.initPasswordPh": "Leave blank to auto-generate; if set, must meet policy",
"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",
"admin.users.usageLiveSkip": "Plan/quota are Usage domain — not on live backend yet (M3). Editable in mock only.",
"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)",
"admin.users.customPwPh": "Password must be at least 12 characters with upper, lower, digit, and symbol",
"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.upgradePlan": "Upgrade plan",
"usage.outcome.title": "This month's outcomes",
"usage.outcome.summary": "Reach {reach} · Conversations {conversations} · Conversions {conversions}",
"usage.outcome.amount": " (~${amount})",
"usage.outcome.emptyHint": "No attributable outcomes this month yet — try patrol or posting.",
"usage.warn.unlimitedOver": "Used {used} credits this month (plan {cap}; limits off — you can continue).",
"usage.warn.exhausted": "Monthly credits are used up. Upgrade or wait for next month.",
"usage.warn.high": "You've used {pct}% of monthly credits.",
"usage.warn.meterNear": "{label} is near its cap ({credits}/{cap} credits).",
"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",
"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;
}