/* i18n.js: translations + language resolution. No auto-run; main.js drives it. */
var supportedLanguages = ["en", "zh-TW", "zh-CN"];
var languageStorageKey = "token-monitor-site-language";

var translations = {
  en: {
    "meta.title": "Token Monitor: AI Tools usage at a glance",
    "meta.description": "Token Monitor is a local-first desktop widget for real-time token, cost, limit, and session monitoring across AI Tools.",
    "meta.ogTitle": "Token Monitor",
    "meta.ogDescription": "Local-first token, cost, limit, and session monitoring for AI Tools.",
    "nav.skip": "Skip to content",
    "nav.primary": "Primary",
    "nav.home": "Token Monitor home",
    "nav.language": "Language",
    "nav.theme": "Toggle light or dark theme",
    "nav.github": "GitHub",
    "nav.sections": "Section navigation",
    "nav.features": "Features",
    "nav.privacy": "Privacy",
    "nav.download": "Download",

    "hero.eyebrow": "Local-first AI coding telemetry",
    "hero.title": "AI Tools usage at a glance",
    "hero.lede": "A local-first desktop widget for real-time token, cost, limit, session, and trend monitoring across AI Tools.",
    "hero.actions": "Primary actions",
    "hero.platforms": "Supported platforms",
    "cta.download": "Download latest release",
    "cta.github": "View on GitHub",

    "tools.eyebrow": "Tracks every tool in your loop",

    "feature.title": "Tokens, limits, trends, and session detail in one view.",
    "feature.live.title": "Live token tracking & cost",
    "feature.live.body": "Watch Claude Code, Codex, Hermes, OpenCode, OpenClaw, Cursor, Antigravity, and Cline update within seconds of each turn, with cost and cache-hit rates alongside every count — themed light or dark to match your setup.",
    "feature.limits.title": "AI Tool Limits before you hit the wall",
    "feature.limits.body": "See Claude Code, Codex, Cursor, Antigravity, OpenCode, and DeepSeek session, weekly, billing, credits, and balance windows, so a limit never surprises you mid-task.",
    "feature.session.title": "Per-session detail on demand",
    "feature.session.body": "Open a Claude Code, Codex, or OpenCode session to see tokens per prompt and per reply, read on-demand from local transcripts or databases. Never synced.",
    "feature.trends.title": "A year of trends, inside the widget",
    "feature.trends.body": "Flip to the Trends view for a twelve-month sparkline with active days, streaks, and your peak day, without leaving the widget. The full dashboard below goes deeper.",
    "feature.status.title": "Provider status, right in the widget",
    "feature.status.body": "Watch Claude, OpenAI, Cursor, and DeepSeek service status without leaving the widget. Each card leads with the active incident title and the count of affected components, and re-checks on your chosen interval.",

    "dash.title": "A year of AI coding, charted.",
    "dash.lede": "Turn on opt-in history and Token Monitor opens a full dashboard window: a GitHub-style activity heatmap with streaks, plus per-tool and per-model usage stacked over time in bar and K-line views, rolled up across all your devices.",
    "mock.you": "YOU",
    "mock.newest": "↕ Newest",
    "mock.session.one": "Compare model spend...",
    "mock.session.two": "Inspect reply details...",

    "surfaces.title": "The same usage, on every surface you already use.",
    "surfaces.menubar.title": "Menu bar & tray",
    "surfaces.menubar.body": "Live cost, tokens, or your closest limit % right next to the clock on macOS and Windows.",
    "surfaces.bubble.title": "Floating Bubble",
    "surfaces.bubble.body": "Collapse the widget into a draggable mini-window with click or hover preview.",
    "surfaces.discord.playing": "Playing",
    "surfaces.discord.title": "Discord Rich Presence",
    "surfaces.discord.body": "Broadcast today's tokens, cost, and top tool to your profile. Opt-in.",
    "surfaces.ios.title": "iOS widget",
    "surfaces.ios.body": "Today's totals on your Home Screen via the Worker hub, with Widgy or Scriptable.",

    "how.title": "Start with one widget. Add a hub for multi-device sync.",
    "how.lede": "Local stays the default path. Add self-hosted sync when you want token usage from multiple devices rolled into one view.",
    "how.local.title": "Local mode",
    "how.local.body": "The widget reads local usage summaries through tokscale and renders them on the same machine. No account, no cloud.",
    "how.pivot.note": "There is no mode toggle. Paste a hub URL and the widget starts syncing; clear the field and everything stays on this machine.",
    "how.sync.title": "Sync mode",
    "how.sync.body": "Each widget or headless agent posts that device's usage summary to your hub, which merges totals and streams them back to every connected widget.",
    "how.node.widget": "Widget",
    "how.node.tokscale": "tokscale",
    "how.node.localLogs": "Local AI logs",
    "how.node.mac": "Mac widget",
    "how.node.windows": "Windows widget",
    "how.node.agent": "Headless agent",
    "how.node.hub": "Self-hosted hub",
    "how.node.summaryStream": "Summary stream",
    "how.backends": "Pick a sync backend; all three speak the same ingest protocol.",
    "how.backends.label": "Self-hostable sync backends",
    "how.backend.widget": "In-widget hub",
    "how.backend.node": "Node CLI hub",
    "how.backend.worker": "Cloudflare Worker",

    "privacy.title": "Your code and conversations are not the product.",
    "privacy.body": "Token Monitor syncs only the fields needed to show totals, costs, tool and model breakdowns, and normalized account limit status.",
    "privacy.payload.cap": "The entire record a hub ever receives: counts, costs, labels, and limit percentages. The account behind each limit is a one-way hash, never the login itself.",
    "privacy.never": "Never syncs",
    "privacy.never.1": "Raw prompts or source files",
    "privacy.never.2": "Conversation transcripts",
    "privacy.never.3": "OAuth credentials or provider responses",

    "final.title": "Download the packaged app and keep every coding tool visible.",
    "final.readme": "Read the setup guide",
    "final.downloads": "Release download options",
    "final.mac.title": "macOS .dmg",
    "final.mac.body": "Apple Silicon, M1 and later",
    "final.win.title": "Windows Setup .exe",
    "final.win.body": "Installer build, recommended",
    "final.source": "Intel Mac, Linux, and source installs are covered in the README for advanced setups.",

    "footer.api": "API docs",
    "footer.worker": "Worker docs",
    "footer.license": "License"
  },

  "zh-TW": {
    "meta.title": "Token Monitor：AI Tools 用量一眼看清",
    "meta.description": "Token Monitor 是為 AI Tools 打造的本地優先桌面 widget，可即時監控 token、成本與限額，查看 session 明細，並透過自架 hub 同步多台裝置。",
    "meta.ogTitle": "Token Monitor",
    "meta.ogDescription": "為 AI Tools 打造的本地優先 token、成本、限額與 session 監控。",
    "nav.skip": "跳到內容",
    "nav.primary": "主要導覽",
    "nav.home": "Token Monitor 首頁",
    "nav.language": "語言",
    "nav.theme": "切換淺色或深色主題",
    "nav.github": "GitHub",
    "nav.sections": "區塊導覽",
    "nav.features": "功能",
    "nav.privacy": "隱私",
    "nav.download": "下載",

    "hero.eyebrow": "本地優先的 AI coding telemetry",
    "hero.title": "AI Tools 用量一眼看清",
    "hero.lede": "為 AI Tools 打造的桌面 widget，即時監控 token、成本、限額、session 與歷史趨勢。",
    "hero.actions": "主要操作",
    "hero.platforms": "支援平台",
    "cta.download": "下載最新版本",
    "cta.github": "查看 GitHub",

    "tools.eyebrow": "涵蓋你工作流裡的每個工具",

    "feature.title": "Token、限制、趨勢與 session 明細，集中在一個畫面。",
    "feature.live.title": "即時 token 追蹤與成本",
    "feature.live.body": "Claude Code、Codex、Hermes、OpenCode、OpenClaw、Cursor、Antigravity、Cline 每輪對話後數秒內更新，每個數字旁都有成本與 cache 命中率，並可切換淺色或深色主題。",
    "feature.limits.title": "在撞牆前看見 AI Tool Limits",
    "feature.limits.body": "看見 Claude Code、Codex、Cursor、Antigravity、OpenCode、DeepSeek 的 session、每週、帳單、credits 與餘額視窗，限制不再在工作中途突襲你。",
    "feature.session.title": "需要時才看 session 明細",
    "feature.session.body": "打開 Claude Code、Codex 或 OpenCode session，看每個 prompt 與 reply 的 token；從本機 transcript 或資料庫即時讀取，永不同步。",
    "feature.trends.title": "一年的趨勢，就在 widget 裡",
    "feature.trends.body": "切到 Trends 視圖，不用離開 widget 就能看到 12 個月的用量長條、活躍天數、連續天數與單日高峰。想看更深入的，往下捲到完整 dashboard。",
    "feature.status.title": "服務狀態，就在 widget 裡",
    "feature.status.body": "不必離開 widget，就能查看 Claude、OpenAI、Cursor 與 DeepSeek 的服務狀態。每張卡片以進行中的事件標題與受影響元件數開頭，並依你設定的間隔重新檢查。",

    "dash.title": "把一年的 AI coding 畫成圖。",
    "dash.lede": "開啟可選的歷史收集，Token Monitor 會打開完整的 dashboard 視窗：GitHub 風格的活動熱力圖與連續天數，加上隨時間堆疊的各工具、各模型用量，提供長條圖與 K 線兩種檢視，並彙整你所有裝置。",
    "mock.you": "你",
    "mock.newest": "↕ 最新",
    "mock.session.one": "比較模型成本...",
    "mock.session.two": "查看 reply 明細...",

    "surfaces.title": "同一份用量，出現在你本來就在用的每個介面。",
    "surfaces.menubar.title": "menu bar 與工作列",
    "surfaces.menubar.body": "macOS 與 Windows 時鐘旁就有即時成本、tokens 或最接近的限制 %。",
    "surfaces.bubble.title": "Floating Bubble",
    "surfaces.bubble.body": "把 widget 收成可拖曳的迷你視窗，支援點擊或 hover 預覽。",
    "surfaces.discord.playing": "正在遊玩",
    "surfaces.discord.title": "Discord Rich Presence",
    "surfaces.discord.body": "把今日 tokens、成本與最常用工具廣播到你的個人檔案，可選開啟。",
    "surfaces.ios.title": "iOS 小工具",
    "surfaces.ios.body": "透過 Worker hub，用 Widgy 或 Scriptable 把今日總量放到主畫面。",

    "how.title": "先用一個 widget。要同步多台裝置時才加 hub。",
    "how.lede": "本地仍是預設路徑。想彙整多台裝置的 Token 用量時，再加一層自架同步。",
    "how.local.title": "本地模式",
    "how.local.body": "Widget 透過 tokscale 讀取本機用量摘要，並在同一台機器上顯示。不需要帳號、不需要雲端。",
    "how.pivot.note": "沒有模式開關。貼上 hub 網址，widget 就開始同步；清空欄位，一切就留在這台機器上。",
    "how.sync.title": "同步模式",
    "how.sync.body": "每個 widget 或 headless agent 會把該裝置的用量摘要送到你的 hub，hub 彙整後再串流回所有已連線 widget。",
    "how.node.widget": "Widget",
    "how.node.tokscale": "tokscale",
    "how.node.localLogs": "本機 AI logs",
    "how.node.mac": "Mac widget",
    "how.node.windows": "Windows widget",
    "how.node.agent": "Headless agent",
    "how.node.hub": "自架 hub",
    "how.node.summaryStream": "摘要串流",
    "how.backends": "同步後端三選一，都走同一套 ingest 協定。",
    "how.backends.label": "可自架的同步後端",
    "how.backend.widget": "widget 內建 hub",
    "how.backend.node": "Node CLI hub",
    "how.backend.worker": "Cloudflare Worker",

    "privacy.title": "你的程式碼與對話不是產品。",
    "privacy.body": "Token Monitor 只同步顯示總量、成本、工具與模型拆分，以及標準化帳戶限制所需的欄位。",
    "privacy.payload.cap": "這就是 hub 收到的完整紀錄：數字、成本、標籤與限制百分比。每個限制背後的帳戶都是單向 hash，永遠不是登入身分本身。",
    "privacy.never": "永不同步",
    "privacy.never.1": "原始提示詞或原始碼",
    "privacy.never.2": "對話 transcript",
    "privacy.never.3": "OAuth 憑證或 provider 回應",

    "final.title": "下載打包好的 App，讓每個 coding 工具的用量都看得見。",
    "final.readme": "閱讀設定指南",
    "final.downloads": "Release 下載選項",
    "final.mac.title": "macOS .dmg",
    "final.mac.body": "Apple Silicon，M1 或更新機型",
    "final.win.title": "Windows Setup .exe",
    "final.win.body": "建議使用安裝版",
    "final.source": "Intel Mac、Linux 與原始碼啟動方式請看 README，適合進階設定。",

    "footer.api": "API 文件",
    "footer.worker": "Worker 文件",
    "footer.license": "授權"
  },

  "zh-CN": {
    "meta.title": "Token Monitor：AI Tools 用量一眼看清",
    "meta.description": "Token Monitor 是为 AI Tools 打造的本地优先桌面组件，可实时监控 token、成本与限额，查看 session 明细，并通过自托管 hub 同步多台设备。",
    "meta.ogTitle": "Token Monitor",
    "meta.ogDescription": "为 AI Tools 打造的本地优先 token、成本、限额与 session 监控。",
    "nav.skip": "跳到内容",
    "nav.primary": "主要导航",
    "nav.home": "Token Monitor 首页",
    "nav.language": "语言",
    "nav.theme": "切换浅色或深色主题",
    "nav.github": "GitHub",
    "nav.sections": "区块导航",
    "nav.features": "功能",
    "nav.privacy": "隐私",
    "nav.download": "下载",

    "hero.eyebrow": "本地优先的 AI coding telemetry",
    "hero.title": "AI Tools 用量一眼看清",
    "hero.lede": "为 AI Tools 打造的桌面组件，实时监控 token、成本、限额、session 与历史趋势。",
    "hero.actions": "主要操作",
    "hero.platforms": "支持平台",
    "cta.download": "下载最新版本",
    "cta.github": "查看 GitHub",

    "tools.eyebrow": "覆盖你工作流里的每个工具",

    "feature.title": "Token、限制、趋势与 session 明细，集中在一个界面。",
    "feature.live.title": "实时 token 追踪与成本",
    "feature.live.body": "Claude Code、Codex、Hermes、OpenCode、OpenClaw、Cursor、Antigravity、Cline 每轮对话后数秒内更新，每个数字旁都有成本与 cache 命中率，并可切换浅色或深色主题。",
    "feature.limits.title": "在撞墙前看见 AI Tool Limits",
    "feature.limits.body": "看见 Claude Code、Codex、Cursor、Antigravity、OpenCode、DeepSeek 的 session、每周、账单、credits 与余额窗口，限制不再在工作中途突袭你。",
    "feature.session.title": "需要时才看 session 明细",
    "feature.session.body": "打开 Claude Code、Codex 或 OpenCode session，看每个 prompt 与 reply 的 token；从本机 transcript 或数据库实时读取，永不同步。",
    "feature.trends.title": "一年的趋势，就在 widget 里",
    "feature.trends.body": "切到 Trends 视图，不用离开 widget 就能看到 12 个月的用量柱状、活跃天数、连续天数与单日峰值。想看更深入的，往下滚到完整 dashboard。",
    "feature.status.title": "服务状态，就在 widget 里",
    "feature.status.body": "不必离开 widget，就能查看 Claude、OpenAI、Cursor 与 DeepSeek 的服务状态。每张卡片以进行中的事件标题与受影响组件数开头，并按你设定的间隔重新检查。",

    "dash.title": "把一年的 AI coding 画成图。",
    "dash.lede": "开启可选的历史收集，Token Monitor 会打开完整的 dashboard 窗口：GitHub 风格的活动热力图与连续天数，加上随时间堆叠的各工具、各模型用量，提供柱状图与 K 线两种视图，并汇总你所有设备。",
    "mock.you": "你",
    "mock.newest": "↕ 最新",
    "mock.session.one": "比较模型成本...",
    "mock.session.two": "查看 reply 明细...",

    "surfaces.title": "同一份用量，出现在你本来就在用的每个界面。",
    "surfaces.menubar.title": "menu bar 与任务栏",
    "surfaces.menubar.body": "macOS 与 Windows 时钟旁就有实时成本、tokens 或最接近的限制 %。",
    "surfaces.bubble.title": "Floating Bubble",
    "surfaces.bubble.body": "把 widget 收成可拖拽的迷你窗口，支持点击或 hover 预览。",
    "surfaces.discord.playing": "正在玩",
    "surfaces.discord.title": "Discord Rich Presence",
    "surfaces.discord.body": "把今日 tokens、成本与最常用工具广播到你的个人资料，可选开启。",
    "surfaces.ios.title": "iOS 小组件",
    "surfaces.ios.body": "通过 Worker hub，用 Widgy 或 Scriptable 把今日总量放到主屏幕。",

    "how.title": "先用一个 widget。要同步多台设备时才加 hub。",
    "how.lede": "本地仍是默认路径。想汇总多台设备的 Token 用量时，再加一层自托管同步。",
    "how.local.title": "本地模式",
    "how.local.body": "Widget 通过 tokscale 读取本机用量摘要，并在同一台机器上显示。不需要账号、不需要云端。",
    "how.pivot.note": "没有模式开关。粘贴 hub 网址，widget 就开始同步；清空字段，一切就留在这台机器上。",
    "how.sync.title": "同步模式",
    "how.sync.body": "每个 widget 或 headless agent 会把该设备的用量摘要送到你的 hub，hub 汇总后再流式推送回所有已连接 widget。",
    "how.node.widget": "Widget",
    "how.node.tokscale": "tokscale",
    "how.node.localLogs": "本机 AI logs",
    "how.node.mac": "Mac widget",
    "how.node.windows": "Windows widget",
    "how.node.agent": "Headless agent",
    "how.node.hub": "自托管 hub",
    "how.node.summaryStream": "摘要流",
    "how.backends": "同步后端三选一，都走同一套 ingest 协定。",
    "how.backends.label": "可自托管的同步后端",
    "how.backend.widget": "widget 内置 hub",
    "how.backend.node": "Node CLI hub",
    "how.backend.worker": "Cloudflare Worker",

    "privacy.title": "你的代码与对话不是产品。",
    "privacy.body": "Token Monitor 只同步显示总量、成本、工具与模型拆分，以及标准化账号限制所需的字段。",
    "privacy.payload.cap": "这就是 hub 收到的完整记录：数字、成本、标签与限制百分比。每个限制背后的账号都是单向 hash，永远不是登录身份本身。",
    "privacy.never": "永不同步",
    "privacy.never.1": "原始提示词或源码",
    "privacy.never.2": "对话 transcript",
    "privacy.never.3": "OAuth 凭证或 provider 响应",

    "final.title": "下载打包好的 App，让每个 coding 工具的用量都看得见。",
    "final.readme": "阅读设置指南",
    "final.downloads": "Release 下载选项",
    "final.mac.title": "macOS .dmg",
    "final.mac.body": "Apple Silicon，M1 或更新机型",
    "final.win.title": "Windows Setup .exe",
    "final.win.body": "建议使用安装版",
    "final.source": "Intel Mac、Linux 与源码启动方式请看 README，适合进阶设置。",

    "footer.api": "API 文档",
    "footer.worker": "Worker 文档",
    "footer.license": "许可证"
  }
};

function normalizeLanguage(value) {
  if (!value) return "";
  var normalized = value.replace("_", "-");
  if (supportedLanguages.indexOf(normalized) !== -1) return normalized;
  var lower = normalized.toLowerCase();
  if (lower === "zh" || lower.indexOf("zh-hant") === 0 || lower === "zh-tw" || lower === "zh-hk" || lower === "zh-mo") return "zh-TW";
  if (lower.indexOf("zh-hans") === 0 || lower === "zh-cn" || lower === "zh-sg") return "zh-CN";
  if (lower.indexOf("en") === 0) return "en";
  return "";
}
function readStoredLanguage() { try { return normalizeLanguage(window.localStorage.getItem(languageStorageKey)); } catch (e) { return ""; } }
function storeLanguage(language) { try { window.localStorage.setItem(languageStorageKey, language); } catch (e) {} }
function languageFromHash() { return normalizeLanguage(window.location.hash.slice(1)); }
function preferredLanguage() { return languageFromHash() || readStoredLanguage() || normalizeLanguage(window.navigator.language) || "en"; }

function translateElement(element, messages) {
  var key = element.getAttribute("data-i18n");
  if (key && messages[key]) element.textContent = messages[key];
  var attrConfig = element.getAttribute("data-i18n-attr");
  if (!attrConfig) return;
  var pairs = attrConfig.split(",");
  for (var i = 0; i < pairs.length; i++) {
    var parts = pairs[i].split(":");
    var attr = (parts[0] || "").trim(), attrKey = (parts[1] || "").trim();
    if (attr && attrKey && messages[attrKey]) element.setAttribute(attr, messages[attrKey]);
  }
}
function applyLanguage(language) {
  var active = supportedLanguages.indexOf(language) !== -1 ? language : "en";
  var messages = translations[active];
  document.documentElement.lang = active;
  document.title = messages["meta.title"];
  var nodes = document.querySelectorAll("[data-i18n], [data-i18n-attr]");
  for (var i = 0; i < nodes.length; i++) translateElement(nodes[i], messages);
  var langBtns = document.querySelectorAll("[data-lang]");
  for (var j = 0; j < langBtns.length; j++) langBtns[j].setAttribute("aria-checked", String(langBtns[j].getAttribute("data-lang") === active));
  var cur = document.querySelector("[data-lang-current]");
  if (cur) cur.textContent = active === "zh-TW" ? "繁" : active === "zh-CN" ? "简" : "EN";
  storeLanguage(active);
  if (window.location.hash !== "#" + active) window.history.replaceState(null, "", "#" + active);
}
function setupLanguageButtons() {
  var btns = document.querySelectorAll("[data-lang]");
  for (var i = 0; i < btns.length; i++) {
    (function (b) { b.addEventListener("click", function () { applyLanguage(b.getAttribute("data-lang")); }); })(btns[i]);
  }
  window.addEventListener("hashchange", function () { applyLanguage(preferredLanguage()); });
}
