import type { AppLocale } from "./types";

/** 扁平 key → 字串；{name} 可插值 */
export type MessageDict = Record<string, string>;

export const zhTW: MessageDict = {
  "app.name": "巡樓",
  "app.nameEn": "Lapras",
  "app.nameZh": "巡樓",
  "app.tagline": "Threads 海巡好幫手",
  "app.taglineEn": "Patrol Threads with ease",
  "nav.today": "今日",
  "nav.crew": "帳號",
  "nav.studio": "創作",
  "nav.scout": "海巡",
  "nav.outbox": "發送",
  "nav.jobs": "任務",
  "nav.brands": "品牌",
  "nav.more": "更多",
  "nav.moreTitle": "更多功能",
  "nav.users": "島民管理",
  "nav.usage": "用量與方案",
  "nav.profile": "會員資料",
  "nav.invite": "邀請關係",
  "nav.settings": "系統設定",
  "nav.logout": "登出",
  "nav.navigate": "導覽",

  "common.save": "儲存",
  "common.cancel": "取消",
  "common.loading": "載入中…",
  "common.back": "返回",
  "common.delete": "刪除",
  "common.edit": "編輯",
  "common.search": "搜尋",
  "common.confirm": "確定",
  "common.optional": "選填",
  "common.success": "已儲存",
  "common.error": "發生錯誤",
  "common.yes": "是",
  "common.no": "否",

  // 後端 envelope code（apps/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": "不能移除或停權最後一位管理員",
  "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 Key（BYOK）繼續使用",
  "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 / admin123（gateway :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.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 ID／Secret 在 gateway 平台設定（yaml／env），Secret 不會顯示。請把 Callback 貼到 Meta 後台，並用 https 公開站連帳。",
  "settings.threadsProvider": "目前模式",
  "settings.threadsProviderFake": "Fake（開發／本機可測 OAuth 流程）",
  "settings.threadsProviderMeta": "Meta 正式",
  "settings.threadsConfigured": "App 憑證",
  "settings.threadsConfiguredYes": "已設定",
  "settings.threadsConfiguredNo": "未設定",
  "settings.threadsCallback": "OAuth Callback URL（redirect_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": "JPG／PNG／WebP，5MB 內。選圖後按「儲存基本資料」寫入；「移除頭像」會立刻清除。",
  "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.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.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.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.syncPosts": "同步已發文",
  "today.syncPostsFail": "同步貼文失敗",
  "today.needAccount": "請先連接 Threads 帳號",
  "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.loading": "載入中…",
  "outbox.detail.sendingHint": "正在發到 Threads（通常 10～30 秒），頁面會自動更新…",
  "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.topicTag": "話題標籤（Threads tag）",
  "compose.topicTagPh": "例如 寵物展（可不加 #）",
  "compose.topicTagHint": "Threads 話題標籤，每則最多一個；1～50 字，勿含 . 或 &。也可在正文寫 #標籤。",
  "compose.tool.mimic": "仿寫",
  "compose.tool.viral": "爆紅分析",
  "compose.tool.research": "上網補資料",
  "compose.tool.image": "產圖",
  "compose.mimic.title": "仿寫別人貼文",
  "compose.mimic.source": "參考全文",
  "compose.mimic.sourcePh": "貼上想仿寫的貼文…",
  "compose.mimic.structureNotes": "結構分析（會帶進仿寫）",
  "compose.mimic.structureNotesPh": "可從「我的貼文 → 分析結構」帶入；或手動貼鉤子／結構／可複製點…",
  "compose.mimic.structureNotesHint": "有填的話，AI 會依此骨架仿寫（語氣仍用人設指紋）。建議先分析再按「仿寫這則」。",
  "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.generating": "生成中…",
  "wizard.topic.aiSuggest": "AI 幫我想",
  "wizard.topic.quickFill": "快速填入",
  "wizard.topic.sampleTitle": "週末咖啡話題",
  "wizard.topic.sampleTopic": "週末想找間不踩雷的咖啡店，插座要多、能坐久。",
  "wizard.topic.aiTitle": "AI 主題",
  "wizard.topic.personaOpen": "{name}開場",
  "wizard.crew.title": "2. 出場",
  "wizard.crew.lead": "主帳",
  "wizard.crew.noUsable": "尚無可用帳號",
  "wizard.crew.unusable": "不可用",
  "wizard.crew.cast": "配角",
  "wizard.script.title": "3. 台詞",
  "wizard.script.persona": "人設",
  "wizard.script.personaNotReady": "人設未就緒",
  "wizard.script.root": "主貼",
  "wizard.script.replyN": "回覆 {n}",
  "wizard.script.generating": "生成中…",
  "wizard.script.ai": "AI 產文",
  "wizard.script.account": "帳號：{name}",
  "wizard.script.noLead": "（未選 lead）",
  "wizard.script.speaker": "發言帳號",
  "wizard.script.leadTag": "（lead）",
  "wizard.script.text": "文案",
  "wizard.script.rootPh": "主貼內容…",
  "wizard.script.replyPh": "回覆內容…",
  "wizard.script.addReply": "新增回覆步驟",
  "wizard.preview.title": "4. 預覽這段對話",
  "wizard.preview.unknown": "未知",
  "wizard.preview.unknownAccount": "未知帳號",
  "wizard.preview.root": "主貼",
  "wizard.preview.leadTalk": "lead 接話",
  "wizard.preview.empty": "（空白）",
  "wizard.schedule.title": "5. 何時發出去",
  "wizard.schedule.start": "第一則（主貼）時間",
  "wizard.schedule.interval": "回覆間隔（分鐘）",
  "wizard.schedule.intervalHint": "相對上一步；送出後後端會加隨機抖動，避免節奏太精準",
  "wizard.submit.title": "6. 送出排程",
  "wizard.submit.body": "確認後會把「{title}」這串互回（共 {n} 步）送進 Outbox，依序用各帳號發出。",
  "wizard.submit.unnamed": "未命名",
  "wizard.submit.root": "主貼",
  "wizard.submit.replyN": "回覆 {n}",
  "wizard.submit.submitting": "提交中…",
  "wizard.submit.run": "提交到 Outbox",

  "reply.account": "用哪個帳號回",
  "reply.persona": "用人設",
  "reply.notReady": "此人設未 ready，無法 AI 產文（仍可手打後發送）。",
  "reply.draft": "回覆草稿",
  "reply.attach": "附圖",
  "reply.generating": "生成中…",
  "reply.ai": "AI 產文",
  "reply.sending": "發送中…",
  "reply.send": "發送",

  "image.attach": "附圖",
  "image.attachFail": "附圖失敗",
  "image.attachedAria": "已附圖片",
  "image.alt": "附圖",
  "image.named": "附圖 {n}",
  "image.remove": "移除圖片",
  "image.full": "已滿 {max} 張",
  "image.more": "再附圖（{n}/{max}）",
  "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.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} 點（約 2～3 週輕度日常）",
  "plan.free.bullet2": "完整功能：創作、海巡、發送、生圖",
  "plan.free.bullet3": "用得出價值再升級 Starter",
  "plan.free.bullet4": "平台忙碌時可改填自己的 Key",
  "plan.free.right1": "可使用完整功能：帳號、創作、海巡、發送、任務與靈感。",
  "plan.free.right2": "點數夠你真實試跑文案、搜尋與幾次生圖，不是空殼 demo。",
  "plan.free.right3": "達上限後升級 Starter 繼續；或設定自備 Key（BYOK）不占平台點。",
  "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": "適合 1～3 人節奏 · 付費主力",
  "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.resend": "重新送出",
  "scout.sending": "發送中…",
  "scout.needAccountBefore": "請先到",
  "scout.needAccountAfter": "連線可用帳號。",
  "scout.knowledge": "周邊知識",
  "scout.knowledgeWithLabel": "周邊知識 · {label}",
  "scout.knowledgeLearn": "周邊知識 · 可學",
  "scout.collapseKnowledge": "收合知識",
  "scout.expandLearn": "展開學習 · {n} 則",
  "scout.expandKnowledge": "展開知識",
  "scout.deleteKnowledgeRun": "刪除此批知識與命中",
  "scout.loadingKnowledge": "正在整理周邊知識…",
  "scout.notesCount": "{n} 則",
  "scout.noKnowledge": "尚無周邊知識",
  "scout.product": "產品",
  "scout.painsSolved": "能解的痛",
  "scout.focus": "焦點",
  "scout.all": "全部",
  "scout.noWebSummary": "尚無網頁摘要",
  "scout.queue": "命中紀錄 · {n}",
  "scout.valueQueue": "痛點／產品接話 · {n}",
  "scout.activityQueue": "活躍短回 · {n}",
  "scout.noMatchesInQueue": "這個佇列暫無命中",
  "scout.collapseQueue": "收合佇列",
  "scout.expandQueue": "展開佇列",
  "scout.noOtherPending": "沒有其他待回",
  "scout.learnPoints": "學習重點",
  "scout.replyHooks": "回帖可借",
  "scout.badgeCore": "最貼主題",
  "scout.unnamedRun": "未命名批次",
  "scout.thisRun": "此批次",
  "scout.confirmDeleteRun": "刪除海巡批次「{label}」？\\n會一併刪除這批命中與周邊知識，無法復原。",
  "scout.deletedRun": "已刪除批次「{label}」",
  "scout.deleteRunFail": "刪除批次失敗",
  "scout.needKeyword": "先填關鍵字",
  "scout.needIntent": "先寫這次要找什麼",
  "scout.productMissing": "所選產品不在列表中，請重新選擇",
  "scout.defaultLabel": "海巡",
  "scout.newRunActivity": "新批次「{label}」· {n} 則待回",
  "scout.newRunValue": "新批次「{label}」· {n} 則 · 請處理「現在這一則」",
  "scout.knowledgeReady": "「{label}」周邊知識已備好 · {n} 則可學",
  "scout.patrolFail": "這輪海巡失敗",
  "scout.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": "接話 · 建關係",
  "scout.tier.core": "最貼主題",
  "scout.tier.coreHint": "直接對準痛點／關鍵語，優先讀",
  "scout.tier.adjacent": "相關周邊",
  "scout.tier.adjacentHint": "鄰近情境，擴搜尋面",
  "scout.tier.broad": "最廣泛",
  "scout.tier.broadHint": "背景與對照，選讀即可",
  "scout.relation.solves_pain": "對準痛點",
  "scout.relation.nearby_scene": "鄰近場景",
  "scout.relation.myth": "迷思澄清",
  "scout.relation.contrast": "對照選購",
  "scout.relation.background": "背景脈絡",

  "brands.title": "品牌",
  "brands.railAria": "品牌列表",
  "brands.railLabel": "你的牌子",
  "brands.add": "新增",
  "brands.brandName": "品牌名稱",
  "brands.brandNamePh": "例如：自家品牌",
  "brands.creating": "建立中…",
  "brands.createBrand": "建立品牌",
  "brands.searchAria": "搜尋品牌",
  "brands.searchPh": "搜尋品牌…",
  "brands.empty": "尚無品牌",
  "brands.noMatch": "無符合",
  "brands.selectAria": "選擇品牌",
  "brands.pickOne": "選一個品牌",
  "brands.inUseHint": "使用中 · 海巡與創作會套用此牌",
  "brands.inUse": "使用中",
  "brands.tabInfo": "牌子資料",
  "brands.tabProducts": "產品",
  "brands.tabProductsN": "產品（{n}）",
  "brands.displayName": "名稱",
  "brands.brief": "摘要",
  "brands.briefPh": "一句話說明這個牌子",
  "brands.audience": "受眾",
  "brands.audiencePh": "誰會在意、為什麼",
  "brands.goals": "目標",
  "brands.goalsPh": "想在 Threads 達成什麼",
  "brands.saving": "儲存中…",
  "brands.deleteBrand": "刪除品牌",
  "brands.searchProductAria": "搜尋產品",
  "brands.searchProductPh": "搜尋產品…",
  "brands.addProduct": "新增產品",
  "brands.noProducts": "尚無產品",
  "brands.hasLink": "有連結",
  "brands.painLabel": "痛點 ",
  "brands.editProduct": "編輯產品",
  "brands.newProduct": "新增產品",
  "brands.importFromUrl": "從商品連結帶入",
  "brands.fetching": "抓取中…",
  "brands.fetch": "抓取",
  "brands.pains": "痛點",
  "brands.painsPh": "一列一個",
  "brands.tags": "標籤",
  "brands.tagsPh": "逗號分隔",
  "brands.intro": "介紹",
  "brands.link": "連結",
  "brands.update": "更新",
  "brands.createItem": "新增",
  "brands.needName": "請輸入名稱",
  "brands.created": "已建立「{name}」",
  "brands.createFail": "建立失敗",
  "brands.saved": "已儲存",
  "brands.saveFail": "儲存失敗",
  "brands.confirmDelete": "確定刪除「{name}」？",
  "brands.deleted": "已刪除",
  "brands.deleteFail": "刪除失敗",
  "brands.fetchFail": "抓取失敗",
  "brands.needLabelContext": "名稱與介紹為必填",
  "brands.productUpdated": "已更新",
  "brands.productAdded": "已新增",
  "brands.confirmDeleteProduct": "刪除此產品？",

  "insights.title": "帳號成效",
  "insights.account": "帳號",
  "insights.noAccount": "尚無帳號",
  "insights.syncing": "同步中…",
  "insights.syncPosts": "同步貼文",
  "insights.myPosts": "我的貼文",
  "insights.pickAccount": "選擇帳號",
  "insights.goAccounts": "帳號",
  "insights.kpiMonth": "本月指標",
  "insights.monthViews": "本月瀏覽",
  "insights.monthLikes": "本月讚",
  "insights.monthReplies": "本月回覆",
  "insights.engRate": "互動率",
  "insights.vsPrev": "vs 上月",
  "insights.avgNear": "近帖均 {rate}",
  "insights.trendTitle": "趨勢與分析 · @{user}",
  "insights.metricViews": "瀏覽",
  "insights.metricLikes": "讚",
  "insights.metricReplies": "回覆",
  "insights.metricPosts": "貼文",
  "insights.metricPostsFull": "貼文數",
  "insights.chartMetrics": "圖表指標",
  "insights.barsAria": "近月{metric}，點柱查看該月分析",
  "insights.barsLabel": "{metric} · 近 {n} 個月",
  "insights.clickBar": " · 點柱看分析",
  "insights.pickMonthAria": "選擇月份",
  "insights.barTitle": "{label}：{value}{est} · 點看分析",
  "insights.est": "（估）",
  "insights.monthSuffix": "{m}月",
  "insights.sparkAria": "趨勢折線，點節點可選月",
  "insights.analysisOf": "{label} 分析",
  "insights.producedAt": "產出於 {time}",
  "insights.hasEstimate": " · 含估測數據",
  "insights.viewsVsPrev": " · 瀏覽 vs 前月 {delta}",
  "insights.statPosts": "貼文",
  "insights.statViews": "瀏覽",
  "insights.statLikes": "讚",
  "insights.statReplies": "回",
  "insights.conclusions": "結論",
  "insights.recommendations": "建議",
  "insights.highlights": "當月亮點",
  "insights.findTopics": "找話題",
  "insights.goScout": "去探查",
  "insights.selectMonth": "選擇月份",
  "insights.topPosts": "表現較佳貼文",
  "insights.noPosts": "尚無貼文",
  "insights.postStats": "瀏覽 {views} · 讚 {likes} · 回 {replies}",
  "insights.openThreads": "開啟 Threads",
  "insights.zeroPct": "0%",
  "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.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": "鎖定發想內容後，用人設口氣改寫成 Threads 正文",
  "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 的 prompt（stream 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 block（post）",
  "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.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": "不擋額度：達方案上限仍可繼續用；AI／Search 次數與點數照樣計算。",
  "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.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": "靈感串場",
  "wizard.topic.fallbackTopic": "生活小題",

  "play.err.needLead": "請選擇主帳號",
  "play.err.needRoot": "請至少有一則主貼",
  "play.err.firstMustRoot": "第一則必須是主貼",
  "play.err.rootMustLead": "主貼必須使用主帳",
  "play.err.rootEmpty": "主貼文案不可空白",
  "play.err.replyAccount": "回覆只能用主帳或已選配角",
  "play.err.replyEmpty": "回覆文案不可空白",
  "play.err.needTarget": "請選擇自己的貼文，或貼上 Threads 連結",
  "play.err.needReplies": "請至少排 1 則留言",
  "play.err.needReplyAccounts": "請至少選一個可回覆帳號",
  "play.err.stepAccount": "每則留言都要指定可用帳號",
  "play.err.stepEmpty": "留言內容不可空白",
  "play.err.notFound": "找不到互回方案",

  "time.justNow": "剛剛",
  "time.minAgo": "{n} 分前",
  "time.hourAgo": "{n} 小時前",
  "time.dayAgo": "{n} 天前",
  "time.min": "{n} 分鐘",
  "time.hour": "{n} 小時",
  "time.day": "{n} 天",
  "time.expired": "已過期 {span}",
  "time.remaining": "剩餘 {span}",
  "time.sessionUnknown": "未記錄到期時間",
  "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.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",

  "common.save": "Save",
  "common.cancel": "Cancel",
  "common.loading": "Loading…",
  "common.back": "Back",
  "common.delete": "Delete",
  "common.edit": "Edit",
  "common.search": "Search",
  "common.confirm": "Confirm",
  "common.optional": "Optional",
  "common.success": "Saved",
  "common.error": "Something went wrong",
  "common.yes": "Yes",
  "common.no": "No",

  "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",
  "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.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.upline": "Invited by",
  "invite.downlines": "Direct invites · {n}",
  "invite.noUpline": "No inviter",
  "invite.noDownline": "None yet",
  "invite.directN": "{n} direct",
  "invite.claimHint": "If you didn’t enter a code at signup, add your inviter’s 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 can’t 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.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.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.syncPosts": "Sync own posts",
  "today.syncPostsFail": "Could not sync posts",
  "today.needAccount": "Connect a Threads account first",
  "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.loading": "Loading…",
  "outbox.detail.sendingHint": "Publishing to Threads (often 10–30s). 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.topicTag": "Topic tag (Threads)",
  "compose.topicTagPh": "e.g. petshow (optional #)",
  "compose.topicTagHint": "One topic tag per post, 1–50 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.structureNotes": "Structure notes (used in mimic)",
  "compose.mimic.structureNotesPh": "From Own posts → Analyze, or paste hooks/structure…",
  "compose.mimic.structureNotesHint": "When set, AI keeps this skeleton while rewriting in your persona voice.",
  "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.generating": "Generating…",
  "wizard.topic.aiSuggest": "AI suggest",
  "wizard.topic.quickFill": "Quick fill",
  "wizard.topic.sampleTitle": "Weekend coffee chat",
  "wizard.topic.sampleTopic": "Looking for a reliable café this weekend — lots of outlets, stay-all-day friendly.",
  "wizard.topic.aiTitle": "AI topic",
  "wizard.topic.personaOpen": "{name} opens",
  "wizard.crew.title": "2. Cast",
  "wizard.crew.lead": "Lead",
  "wizard.crew.noUsable": "No usable accounts",
  "wizard.crew.unusable": "Unavailable",
  "wizard.crew.cast": "Supporting",
  "wizard.script.title": "3. Lines",
  "wizard.script.persona": "Persona",
  "wizard.script.personaNotReady": "Persona not ready",
  "wizard.script.root": "Root post",
  "wizard.script.replyN": "Reply {n}",
  "wizard.script.generating": "Generating…",
  "wizard.script.ai": "AI draft",
  "wizard.script.account": "Account: {name}",
  "wizard.script.noLead": "(no lead)",
  "wizard.script.speaker": "Speaker",
  "wizard.script.leadTag": "(lead)",
  "wizard.script.text": "Copy",
  "wizard.script.rootPh": "Root post text…",
  "wizard.script.replyPh": "Reply text…",
  "wizard.script.addReply": "Add reply step",
  "wizard.preview.title": "4. Preview the thread",
  "wizard.preview.unknown": "Unknown",
  "wizard.preview.unknownAccount": "Unknown account",
  "wizard.preview.root": "Root",
  "wizard.preview.leadTalk": "lead reply",
  "wizard.preview.empty": "(empty)",
  "wizard.schedule.title": "5. When to send",
  "wizard.schedule.start": "First post (root) time",
  "wizard.schedule.interval": "Reply interval (minutes)",
  "wizard.schedule.intervalHint": "Relative to previous step; 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.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 (~2–3 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 1–3 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 site’s 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.resend": "Resend",
  "scout.sending": "Sending…",
  "scout.needAccountBefore": "Connect a usable account under",
  "scout.needAccountAfter": "first.",
  "scout.knowledge": "Related knowledge",
  "scout.knowledgeWithLabel": "Related · {label}",
  "scout.knowledgeLearn": "Related · to learn",
  "scout.collapseKnowledge": "Collapse knowledge",
  "scout.expandLearn": "Expand · {n} notes",
  "scout.expandKnowledge": "Expand knowledge",
  "scout.deleteKnowledgeRun": "Delete this batch's knowledge & hits",
  "scout.loadingKnowledge": "Preparing related knowledge…",
  "scout.notesCount": "{n} notes",
  "scout.noKnowledge": "No related knowledge yet",
  "scout.product": "Product",
  "scout.painsSolved": "Pains we solve",
  "scout.focus": "Focus",
  "scout.all": "All",
  "scout.noWebSummary": "No web summaries yet",
  "scout.queue": "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.learnPoints": "Key takeaways",
  "scout.replyHooks": "Reply hooks",
  "scout.badgeCore": "Closest to topic",
  "scout.unnamedRun": "Unnamed batch",
  "scout.thisRun": "this batch",
  "scout.confirmDeleteRun": "Delete patrol batch “{label}”?\\nHits and related knowledge will be removed. This cannot be undone.",
  "scout.deletedRun": "Deleted batch “{label}”",
  "scout.deleteRunFail": "Failed to delete batch",
  "scout.needKeyword": "Enter keywords first",
  "scout.needIntent": "Write what you're looking for",
  "scout.productMissing": "Selected product is not in the list. Please reselect.",
  "scout.defaultLabel": "Patrol",
  "scout.newRunActivity": "New batch “{label}” · {n} pending",
  "scout.newRunValue": "New batch “{label}” · {n} posts · handle “Now this post”",
  "scout.knowledgeReady": "“{label}” knowledge ready · {n} notes",
  "scout.patrolFail": "This patrol failed",
  "scout.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",
  "scout.tier.core": "Closest",
  "scout.tier.coreHint": "Directly on the pain/keywords — read first",
  "scout.tier.adjacent": "Adjacent",
  "scout.tier.adjacentHint": "Nearby context, broaden search",
  "scout.tier.broad": "Broad",
  "scout.tier.broadHint": "Background & contrast — optional",
  "scout.relation.solves_pain": "Hits the pain",
  "scout.relation.nearby_scene": "Nearby scene",
  "scout.relation.myth": "Myth-busting",
  "scout.relation.contrast": "Contrast shopping",
  "scout.relation.background": "Background",

  "brands.title": "Brands",
  "brands.railAria": "Brand list",
  "brands.railLabel": "Your brands",
  "brands.add": "Add",
  "brands.brandName": "Brand name",
  "brands.brandNamePh": "e.g. your brand",
  "brands.creating": "Creating…",
  "brands.createBrand": "Create brand",
  "brands.searchAria": "Search brands",
  "brands.searchPh": "Search brands…",
  "brands.empty": "No brands yet",
  "brands.noMatch": "No matches",
  "brands.selectAria": "Select brand",
  "brands.pickOne": "Pick a brand",
  "brands.inUseHint": "Active · used for patrol and studio",
  "brands.inUse": "Active",
  "brands.tabInfo": "Brand info",
  "brands.tabProducts": "Products",
  "brands.tabProductsN": "Products ({n})",
  "brands.displayName": "Name",
  "brands.brief": "Summary",
  "brands.briefPh": "One line about this brand",
  "brands.audience": "Audience",
  "brands.audiencePh": "Who cares and why",
  "brands.goals": "Goals",
  "brands.goalsPh": "What you want on Threads",
  "brands.saving": "Saving…",
  "brands.deleteBrand": "Delete brand",
  "brands.searchProductAria": "Search products",
  "brands.searchProductPh": "Search products…",
  "brands.addProduct": "Add product",
  "brands.noProducts": "No products yet",
  "brands.hasLink": "Has link",
  "brands.painLabel": "Pains ",
  "brands.editProduct": "Edit product",
  "brands.newProduct": "New product",
  "brands.importFromUrl": "Import from product URL",
  "brands.fetching": "Fetching…",
  "brands.fetch": "Fetch",
  "brands.pains": "Pain points",
  "brands.painsPh": "One per line",
  "brands.tags": "Tags",
  "brands.tagsPh": "Comma-separated",
  "brands.intro": "Description",
  "brands.link": "Link",
  "brands.update": "Update",
  "brands.createItem": "Add",
  "brands.needName": "Enter a name",
  "brands.created": "Created “{name}”",
  "brands.createFail": "Create failed",
  "brands.saved": "Saved",
  "brands.saveFail": "Save failed",
  "brands.confirmDelete": "Delete “{name}”?",
  "brands.deleted": "Deleted",
  "brands.deleteFail": "Delete failed",
  "brands.fetchFail": "Fetch failed",
  "brands.needLabelContext": "Name and description are required",
  "brands.productUpdated": "Updated",
  "brands.productAdded": "Added",
  "brands.confirmDeleteProduct": "Delete this product?",

  "insights.title": "Account performance",
  "insights.account": "Account",
  "insights.noAccount": "No accounts",
  "insights.syncing": "Syncing…",
  "insights.syncPosts": "Sync posts",
  "insights.myPosts": "My posts",
  "insights.pickAccount": "Select an account",
  "insights.goAccounts": "Accounts",
  "insights.kpiMonth": "This month",
  "insights.monthViews": "Views this month",
  "insights.monthLikes": "Likes this month",
  "insights.monthReplies": "Replies this month",
  "insights.engRate": "Engagement",
  "insights.vsPrev": "vs last month",
  "insights.avgNear": "Recent avg {rate}",
  "insights.trendTitle": "Trends & analysis · @{user}",
  "insights.metricViews": "Views",
  "insights.metricLikes": "Likes",
  "insights.metricReplies": "Replies",
  "insights.metricPosts": "Posts",
  "insights.metricPostsFull": "Posts",
  "insights.chartMetrics": "Chart metric",
  "insights.barsAria": "Recent months {metric}; click a bar for analysis",
  "insights.barsLabel": "{metric} · last {n} months",
  "insights.clickBar": " · click bar for analysis",
  "insights.pickMonthAria": "Select month",
  "insights.barTitle": "{label}: {value}{est} · click for analysis",
  "insights.est": " (est.)",
  "insights.monthSuffix": "{m}",
  "insights.sparkAria": "Trend line; click a node to select month",
  "insights.analysisOf": "{label} analysis",
  "insights.producedAt": "Generated {time}",
  "insights.hasEstimate": " · includes estimates",
  "insights.viewsVsPrev": " · views vs prev {delta}",
  "insights.statPosts": "Posts",
  "insights.statViews": "Views",
  "insights.statLikes": "Likes",
  "insights.statReplies": "Replies",
  "insights.conclusions": "Takeaways",
  "insights.recommendations": "Recommendations",
  "insights.highlights": "Month highlights",
  "insights.findTopics": "Find topics",
  "insights.goScout": "Go patrol",
  "insights.selectMonth": "Select a month",
  "insights.topPosts": "Top posts",
  "insights.noPosts": "No posts yet",
  "insights.postStats": "Views {views} · likes {likes} · replies {replies}",
  "insights.openThreads": "Open Threads",
  "insights.zeroPct": "0%",
  "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.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 don’t 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": "Ideate → write in persona → take it",
  "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": "Write in persona",
  "inspire.generateHint": "Lock ideas, then rewrite into a Threads post in your persona voice",
  "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.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.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 Da’an is fine but crowded",

  "inspire.playTitle": "Inspired thread",
  "wizard.topic.fallbackTopic": "Everyday topic",

  "play.err.needLead": "Pick a lead account",
  "play.err.needRoot": "Add at least one root post",
  "play.err.firstMustRoot": "The first step must be the root post",
  "play.err.rootMustLead": "Root post must use the lead account",
  "play.err.rootEmpty": "Root post text cannot be empty",
  "play.err.replyAccount": "Replies can only use lead or selected cast accounts",
  "play.err.replyEmpty": "Reply text cannot be empty",
  "play.err.needTarget": "Pick one of your posts, or paste a Threads link",
  "play.err.needReplies": "Add at least one reply",
  "play.err.needReplyAccounts": "Pick at least one reply account",
  "play.err.stepAccount": "Every reply needs a usable account",
  "play.err.stepEmpty": "Reply text cannot be empty",
  "play.err.notFound": "Play not found",

  "time.justNow": "Just now",
  "time.minAgo": "{n}m ago",
  "time.hourAgo": "{n}h ago",
  "time.dayAgo": "{n}d ago",
  "time.min": "{n} min",
  "time.hour": "{n} hr",
  "time.day": "{n} day",
  "time.expired": "Expired {span}",
  "time.remaining": "{span} left",
  "time.sessionUnknown": "Session not recorded",
  "time.sessionExpired": "Session expired · {absolute}",
  "time.sessionSoon": "Session expiring · {relative} ({absolute})",
  "time.sessionOk": "Session OK · {relative} ({absolute})",
};

const catalogs: Record<AppLocale, MessageDict> = {
  "zh-TW": zhTW,
  en,
};

export function getCatalog(locale: AppLocale): MessageDict {
  return catalogs[locale] || zhTW;
}

export function translate(
  locale: AppLocale,
  key: string,
  params?: Record<string, string | number>,
): string {
  const dict = getCatalog(locale);
  let s = dict[key] ?? zhTW[key] ?? key;
  if (params) {
    for (const [k, v] of Object.entries(params)) {
      s = s.replace(new RegExp(`\\{${k}\\}`, "g"), String(v));
    }
  }
  return s;
}
