{
  "common.cancel": "Cancel",
  "common.save": "Save",
  "common.saveSettings": "Save settings",
  "common.loading": "Loading…",
  "common.delete": "Delete",
  "common.modify": "Modify",
  "common.next": "Next",
  "common.prev": "Previous",
  "common.refresh": "Refresh",
  "common.notFound": "(not found)",
  "common.copied": "Copied",
  "common.copy": "Copy",
  "common.close": "Close",

  "sidebar.brand.tag": "Multi-subscription proxy",
  "sidebar.nav.guide": "Setup guide",
  "sidebar.nav.virtualModels": "Virtual models",
  "sidebar.nav.subscriptions": "Subscriptions",
  "sidebar.nav.requestLogs": "Request logs",
  "sidebar.nav.logs": "Logs",
  "sidebar.nav.statistics": "Statistics",
  "sidebar.nav.settings": "Settings",
  "sidebar.nav.about": "About",
  "sidebar.updateAvailable": "Update available",

  "settings.title": "Settings",
  "settings.subtitle": "Proxy service, client config, authentication and data retention.",
  "settings.section.update": "App updates",
  "settings.update.source.label": "Update source",
  "settings.update.source.international": "Global",
  "settings.update.source.china": "Mainland China",
  "settings.section.proxy": "Proxy service",
  "settings.proxy.statusRunning": "Running",
  "settings.proxy.statusStopped": "Stopped",
  "settings.proxy.port.label": "Listen port",
  "settings.proxy.port.desc": "Default 23456. Auto-increments when the port is in use.",
  "settings.proxy.port.actual": "Actual:",
  "settings.proxy.bind.label": "Listen address",
  "settings.proxy.bind.desc": "Default is loopback only. With \"LAN accessible\" on, other devices can point Claude Code at this machine's IP.",
  "settings.proxy.bind.local": "Loopback only",
  "settings.proxy.bind.lan": "LAN",
  "settings.proxy.bind.aria": "LAN accessible",
  "settings.proxy.bind.warning": "⚠️ When enabled, any device on the same network can reach the proxy. The proxy itself does no auth — be careful on untrusted networks.",
  "settings.proxy.autostart.label": "Launch at startup",
  "settings.proxy.needsRestart": "Proxy config changed (protocol/port/listen address). Restart cc-router to take effect.",
  "settings.proxy.mode.label": "Listen protocol",
  "settings.proxy.mode.desc": "\"HTTP only\" is the simplest; \"HTTPS only\" requires importing the CA below into the system trust store; \"both\" exposes HTTP and HTTPS on separate ports so different clients can pick their own.",
  "settings.proxy.mode.http": "HTTP only",
  "settings.proxy.mode.https": "HTTPS only",
  "settings.proxy.mode.both": "HTTP + HTTPS",
  "settings.proxy.httpsPort.label": "HTTPS port",
  "settings.proxy.httpsPort.desc": "Default 23457. Auto-increments when the port is in use, and also steps around HTTP port conflicts.",

  "settings.section.https": "HTTPS certificate",
  "settings.https.h2.label": "HTTP/2 protocol",
  "settings.https.h2.desc": "When enabled, the HTTPS port advertises HTTP/2 via TLS ALPN — clients can negotiate h2, falling back to HTTP/1.1 on failure. When disabled, HTTP/1.1 is forced. Takes effect after restarting cc-router.",
  "settings.https.cert.fingerprint.label": "CA fingerprint (SHA-256)",
  "settings.https.cert.fingerprint.desc": "Use this to verify the cert in your system trust store is the same CA. A matching fingerprint means the import succeeded.",
  "settings.https.cert.export.label": "Export CA certificate",
  "settings.https.cert.export.desc": "Export cc-router's self-signed CA public key. Both .pem and .crt are written (identical content). On Windows, double-click the .crt to launch the certificate install wizard; on macOS/Linux either .pem or .crt works. Once imported into the system trust store, browsers and clients will trust the localhost certificates cc-router issues.",
  "settings.https.cert.export.button": "Export CA certificate…",
  "settings.https.cert.exportOk": "Exported both .pem and .crt of the CA. Follow the steps below to import it into your system trust store.",
  "settings.https.cert.exportFailed": "Export failed",
  "settings.https.cert.regenerate.button": "Regenerate certificate",
  "settings.https.cert.regenerateConfirm": "Regenerate the leaf certificate? This does not affect the CA already imported into your trust store; the new cert takes effect after restarting the app.",
  "settings.https.cert.regenerateOk": "Leaf certificate regenerated. Takes effect after restarting cc-router.",
  "settings.https.cert.regenerateFailed": "Regenerate failed",
  "settings.https.cert.sans.label": "Extra SANs (IP / hostname)",
  "settings.https.cert.sans.desc": "One IP or hostname per line (e.g. 192.168.1.5 or my-laptop.local). localhost / 127.0.0.1 / ::1 are always in the cert — this list appends to them. The leaf cert regenerates when this field loses focus; restart cc-router for it to take effect.",
  "settings.https.cert.sans.regenerated": "Leaf cert regenerated with the new SANs. Takes effect after restarting cc-router.",
  "settings.https.cert.howto.title": "Import into the system trust store (one-time after export — every cert cc-router issues afterwards will be trusted)",
  "settings.https.cert.howto.macos": "Double-click the .pem → Keychain Access → select \"cc-router local CA\" → right-click \"Get Info\" → expand \"Trust\" → set \"When using this certificate\" to \"Always Trust\" → close the window and confirm with your password.",
  "settings.https.cert.howto.windows": "Double-click the .crt → Install Certificate → choose \"Local Machine\" (admin required) → \"Place all certificates in the following store\" → browse to \"Trusted Root Certification Authorities\" → Finish.",
  "settings.https.cert.howto.linux": "Copy the .crt to /usr/local/share/ca-certificates/, then sudo update-ca-certificates. Firefox/Chromium use their own trust stores — import separately in browser settings.",
  "settings.saveFailed": "Save failed",
  "settings.section.auth": "Authentication & CORS",
  "settings.auth.token.label": "Token authentication",
  "settings.auth.token.desc": "Set ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN to this token when launching Claude Code. After regenerating, every configured client must be updated.",
  "settings.auth.token.enabled": "Enabled — requests must carry a valid token",
  "settings.auth.token.disabled": "Disabled — all requests pass through",
  "settings.auth.token.regenerated": "Generated",
  "settings.auth.token.regenerate": "Regenerate",
  "settings.auth.token.alertFailed": "Token generation failed",
  "settings.auth.cors.label": "CORS",
  "settings.auth.cors.descEnabled": "Enabled — responses carry CORS headers. Set a specific value like http://localhost:5173 to allow only that origin.",
  "settings.auth.cors.descDisabled": "Disabled — browser cross-origin calls will be blocked.",
  "settings.auth.cors.statusEnabled": "Enabled — responses carry CORS headers",
  "settings.auth.cors.statusDisabled": "Disabled — browser cross-origin calls will be blocked",
  "settings.section.storage": "Data storage",
  "settings.storage.retention.label": "Request log retention",
  "settings.storage.retention.7d": "7 days",
  "settings.storage.retention.30d": "30 days",
  "settings.storage.retention.90d": "90 days",
  "settings.storage.retention.forever": "Forever",
  "settings.storage.dbLimit.label": "Database size limit",
  "settings.storage.dbLimit.unlimited": "10 GB (effectively unlimited)",
  "settings.section.language": "Language",
  "settings.language.label": "UI language",
  "settings.language.desc": "Choose the cc-router UI display language. \"Follow system\" reads your system locale: Chinese → 中文, Japanese → 日本語, otherwise → English.",
  "settings.language.system": "Follow system",
  "settings.section.debug": "Debug",
  "settings.debug.mode.label": "Debug mode",
  "settings.debug.mode.desc": "When on, every outbound request writes three .txt files to the debug-dumps directory: the client request body, cc-router's rewritten request body, and the upstream response body. Useful for protocol adaptation issues. Files contain full conversation content — turn off and clean up after debugging.",
  "settings.debug.dumps.label": "Dump directory",
  "settings.debug.dumps.desc": "Files accumulate over time; please clean up periodically.",
  "settings.debug.open.button": "Open dump directory",
  "settings.debug.open.alertFailed": "Failed to open directory",
  "settings.debug.clear.button": "Clear dumps",
  "settings.debug.clear.alertFailed": "Clear failed",
  "settings.debug.clear.dialog.title": "Clear debug-dumps?",
  "settings.debug.clear.dialog.desc": "This permanently deletes all .txt files under the debug-dumps directory. Samples you've already shared with Claude for debugging are safe to remove.",
  "settings.debug.clear.dialog.confirm": "Confirm and clear",
  "settings.section.danger": "Danger zone · Factory reset",
  "settings.danger.desc": "Erase all subscriptions, API keys, virtual model bindings, request logs and settings. The app restarts into the initial welcome page. This cannot be undone.",
  "settings.danger.button": "Factory reset",
  "settings.danger.alertFailed": "Factory reset failed",
  "settings.danger.dialog.title": "Confirm factory reset?",
  "settings.danger.dialog.intro": "The following will be permanently deleted:",
  "settings.danger.dialog.item.subscriptions": "All subscriptions (including plaintext API keys)",
  "settings.danger.dialog.item.virtualModels": "Virtual model bindings",
  "settings.danger.dialog.item.logs": "Request logs and model list cache",
  "settings.danger.dialog.item.settings": "App settings (port, retention, etc.)",
  "settings.danger.dialog.outro": "The app will restart automatically when done.",
  "settings.danger.dialog.confirm": "Confirm and restart",

  "about.title": "About",
  "about.subtitle": "Project info & license",
  "about.description": "A local HTTP proxy that aggregates multiple LLM subscriptions into a single Anthropic Messages API endpoint, letting Claude Code switch between them transparently.",
  "about.repo": "GitHub repo",
  "about.docs": "Docs",
  "about.site": "Website",
  "about.updater.checking": "Checking for updates…",
  "about.updater.upToDate": "You're on the latest version",
  "about.updater.idle": "Check for app updates",
  "about.updater.recheck": "Recheck",
  "about.updater.check": "Check",
  "about.updater.foundNewPrefix": "Found new version v",
  "about.updater.currentPrefix": "Current v",
  "about.updater.debManual": " · deb packages don't support in-place upgrade; please reinstall manually",
  "about.updater.openDownload": "Open download page",
  "about.updater.installNow": "Install now",
  "about.updater.downloadingPrefix": "Downloading v",
  "about.updater.ready.title": "Update ready",
  "about.updater.ready.desc": "Takes effect after restart. Restarting will briefly interrupt Claude Code's current session — do it at a convenient time.",
  "about.updater.restart": "Restart now",
  "about.updater.error": "Update check failed",
  "about.updater.retry": "Retry",
  "about.disclaimer.title": "Disclaimer",
  "about.disclaimer.usage": "This tool only switches between subscription plans you already own. Request bodies are passed through almost verbatim — no reverse engineering, no jailbreak, no circumvention. You are responsible for complying with each plan's terms of service. cc-router is intended for use with coding tools like Claude Code only; do not use it for anything else.",
  "about.disclaimer.tos": "Provider terms of service do not necessarily allow \"routing a subscription key through a third-party proxy with multi-virtual-model dispatch\" — especially for per-seat subscriptions like Coding Plans / Token Plans, where this pattern may trip risk controls. The author assumes no liability for any account being throttled, banned, or having its subscription cancelled as a result of using this tool.",
  "about.disclaimer.warranty": "This software is provided As-Is, without warranty of any kind. The author is not liable for any direct or indirect damages arising from its use, including but not limited to abnormal quota consumption, data loss, or business interruption.",
  "onboarding.disclaimer.title": "Disclaimer",
  "onboarding.disclaimer.subtitle": "Please read the following before you start using cc-router.",
  "onboarding.disclaimer.accept": "I have read and agree",

  "guide.title": "Setup guide",
  "guide.subtitle": "Use cc-router as an Anthropic Messages-compatible endpoint for various clients.",
  "guide.proxy.title": "Proxy listen address",
  "guide.proxy.statusNotStarted": "Not started",
  "guide.proxy.intro1": "cc-router runs a local HTTP proxy that aggregates subscriptions into a single Anthropic Messages endpoint. Port, listen address and auth token can be changed in",
  "guide.proxy.settingsLink": "Settings",
  "guide.proxy.intro2": " (port and address changes require restarting the app).",
  "guide.method1.title": "Method 1 · Write to settings.json (recommended)",
  "guide.method1.sub": "Most reliable, no shell environment dependency",
  "guide.method1.desc": "Merge the JSON below into Claude Code's config file. If the file doesn't exist, create it.",
  "guide.method1.note1": " is filled in with the current cc-router token, ready to use. The token can be regenerated in",
  "guide.method1.note2": ".",
  "guide.method2.title": "Method 2 · Environment variables (alternative)",
  "guide.method2.sub": "GUI-launched clients may not see shell env — prefer Method 1",
  "guide.method2.note1": "Add the lines above to ",
  "guide.method2.note2": ", ",
  "guide.method2.note3": " or your PowerShell profile, restart your terminal, then launch Claude Code.",

  "guide.tab.others": "Other AI agents",
  "guide.others.title": "More integrations coming",

  "guide.ccswitch.entry.title": "Add a new provider in cc-switch",
  "guide.ccswitch.entry.body": "In cc-switch → click \"Add new provider\" → switch to the \"Claude providers\" tab → choose \"Custom configuration\" (don't pick one of the presets).",
  "guide.ccswitch.method1.title": "Method 1 · Fill in the form",
  "guide.ccswitch.method1.sub": "Straightforward — good for first-time setup",
  "guide.ccswitch.method1.desc": "Fill in the fields below. Already populated with cc-router's current port and token — click each value to copy.",
  "guide.ccswitch.method1.fieldUrl": "Endpoint URL",
  "guide.ccswitch.method1.fieldKey": "API Key",
  "guide.ccswitch.method1.fieldFormat": "API format",
  "guide.ccswitch.method1.fieldAuthField": "Auth field",
  "guide.ccswitch.method1.modelMapTitle": "Expand \"Advanced options\" and fill in \"Model mapping\":",
  "guide.ccswitch.method1.modelOpus": "Primary / Default Opus model",
  "guide.ccswitch.method1.modelSonnet": "Default Sonnet model",
  "guide.ccswitch.method1.modelHaiku": "Default Haiku model",
  "guide.ccswitch.method1.note": "Don't add a trailing slash to the endpoint URL — cc-switch will reject it.",
  "guide.ccswitch.method2.title": "Method 2 · Paste JSON directly",
  "guide.ccswitch.method2.sub": "One-shot paste, skip the form",
  "guide.ccswitch.method2.desc": "Paste the JSON below into cc-switch's \"Config JSON\" editor — sets everything in one go. Already populated with cc-router's current port and token.",

  "guide.openclaw.path.title": "Config file path",
  "guide.openclaw.path.note": "Supports .js / .json / .yaml — use whichever you prefer.",
  "guide.openclaw.config.title": "Full config example",
  "guide.openclaw.config.desc": "Write the content below into the file (create it if missing). Filled in with cc-router's current port and token, ready to use.",
  "guide.openclaw.note.modelRef": "Model refs must use the anthropic/<model-name> prefixed form. cc-router exposes model-opus / model-sonnet / model-haiku as virtual models; any other model name passes through to fallback.",
  "guide.openclaw.note.tokenHint": "The token can be regenerated on the Settings page.",

  "guide.hermes.path.title": "Config file path",
  "guide.hermes.path.note": "Or generate it interactively with the hermes model command — no manual editing required.",
  "guide.hermes.config.title": "Config example",
  "guide.hermes.config.desc": "Write the content below into the config file. Filled in with cc-router's current port, ready to use.",
  "guide.hermes.auth.title": "API Key configuration",
  "guide.hermes.auth.desc": "Use the ANTHROPIC_API_KEY environment variable, or run hermes auth add anthropic --type api-key --api-key <token>. The token is shown and regenerated on the Settings page.",
  "guide.hermes.note.apiMode": "api_mode must be anthropic_messages (the option in Hermes that matches cc-router's protocol). Anything else mismatches the protocol and 4xx's everything.",

  "guide.opencode.path.title": "Config file path",
  "guide.opencode.path.project": "Project",
  "guide.opencode.path.global": "Global",
  "guide.opencode.path.note": "Pick either project-level opencode.json or the global ~/.config/opencode/opencode.json.",
  "guide.opencode.config.title": "Config example",
  "guide.opencode.config.desc": "The @ai-sdk/anthropic npm package declares this as an Anthropic-protocol endpoint. Filled in with cc-router's current port and token, ready to use.",
  "guide.opencode.note.baseUrlTrap": "⚠️ Don't append /v1 to baseURL. @ai-sdk/anthropic auto-appends /v1/messages internally, so doubling up gives /v1/v1/messages → 404 (this is the cause of OpenCode issue #5163).",
  "guide.opencode.note.usage": "Use /models and pick cc-router/model-opus (or sonnet / haiku).",

  "stats.title": "Statistics",
  "stats.subtitle": "Global aggregation of usage, duration, and success rate. Data is rolled up daily and kept permanently — unaffected by log retention cleanup.",
  "stats.refresh": "Refresh",
  "stats.range.today": "Today",
  "stats.range.last7": "Last 7 days",
  "stats.range.last30": "Last 30 days",
  "stats.range.last90": "Last 90 days",
  "stats.range.all": "All time",
  "stats.kpi.totalRequests": "Total requests",
  "stats.kpi.successRate": "Success rate",
  "stats.kpi.avgDuration": "Avg duration",
  "stats.kpi.totalTokens": "Total tokens",
  "stats.kpi.failedFormat": "{failed} failed / {total}",
  "stats.kpi.p95Prefix": "P95 ",
  "stats.kpi.p95Suffix": " s",
  "stats.heatmap.title": "Token usage heatmap",
  "stats.heatmap.subtitle": "Daily token consumption over the last 365 days. Darker means more usage.",
  "stats.heatmap.legendLess": "Less",
  "stats.heatmap.legendMore": "More",
  "stats.heatmap.tooltipFormat": "{date}: {tokens} tokens · {requests} requests",
  "stats.heatmap.empty": "No recent usage data.",
  "stats.daily.title": "Daily trend",
  "stats.daily.subtitle": "Request volume by day. Green = success, red = error, gray = timeout.",
  "stats.daily.empty": "No requests in the selected range.",
  "stats.daily.tooltipRequests": "Requests",
  "stats.daily.tooltipSuccess": "Success",
  "stats.daily.tooltipError": "Error",
  "stats.daily.tooltipTimeout": "Timeout",
  "stats.daily.tokenTitle": "Token usage by day",
  "stats.daily.tokenSubtitle": "Token volume by day, bottom to top: cache read / cache write / input / output.",
  "stats.daily.tokenTooltipOutput": "Output",
  "stats.daily.tokenTooltipInput": "Input",
  "stats.daily.tokenTooltipCacheCreate": "Cache write",
  "stats.daily.tokenTooltipCacheRead": "Cache read",
  "stats.byVm.title": "Virtual model breakdown",
  "stats.byVm.subtitle": "Requests and success rate per virtual model slot.",
  "stats.byVm.empty": "No data in the selected range.",
  "stats.bySub.title": "Subscription ranking",
  "stats.bySub.subtitle": "Click a row to jump to the logs page filtered by that subscription.",
  "stats.bySub.col.subscription": "Subscription",
  "stats.bySub.col.requests": "Requests",
  "stats.bySub.col.successRate": "Success rate",
  "stats.bySub.col.avgDuration": "Avg duration",
  "stats.bySub.col.tokensOut": "Output tokens",
  "stats.bySub.empty": "No subscription data in the selected range.",

  "requestLogs.title": "Request logs",
  "requestLogs.subtitle": "Recent requests through the proxy, newest first.",
  "requestLogs.refresh": "Refresh",
  "requestLogs.filter.allVm": "All virtual models",
  "requestLogs.filter.allProvider": "All providers",
  "requestLogs.filter.allStatus": "All statuses",
  "requestLogs.filter.allClient": "All clients",
  "requestLogs.filter.clientUnknown": "Unrecognized",
  "requestLogs.summaryFormat": "{total} items · page {page} of {pages}",
  "requestLogs.summaryEmpty": "0 items",
  "requestLogs.empty.filtered": "No records under current filter.",
  "requestLogs.empty.none": "No request logs yet. Run a Claude Code conversation through the proxy to see records.",
  "requestLogs.clearFilter": "Clear filter",
  "requestLogs.col.time": "Time",
  "requestLogs.col.status": "Status",
  "requestLogs.col.client": "Client",
  "requestLogs.col.virtualModel": "Virtual model",
  "requestLogs.col.realModel": "Real model",
  "requestLogs.col.responseModel": "Response model",
  "requestLogs.col.provider": "Provider",
  "requestLogs.col.tokensIn": "In",
  "requestLogs.col.tokensOut": "Out",
  "requestLogs.col.latency": "Latency",
  "requestLogs.status.success": "Success",
  "requestLogs.status.timeout": "Timeout",
  "requestLogs.status.error": "Error",
  "requestLogs.sse": "SSE stream",
  "requestLogs.prevPage": "Previous",
  "requestLogs.nextPage": "Next",
  "requestLogs.detail.title": "Request detail",
  "requestLogs.detail.time": "Time",
  "requestLogs.detail.requestId": "Request ID",
  "requestLogs.detail.status": "Status",
  "requestLogs.detail.httpStatus": "Upstream HTTP",
  "requestLogs.detail.virtualModel": "Virtual model",
  "requestLogs.detail.realModel": "Real model",
  "requestLogs.detail.provider": "Provider",
  "requestLogs.detail.latency": "Latency",
  "requestLogs.detail.errorMessage": "Error message",
  "requestLogs.detail.upstreamBody": "Upstream response (truncated)",
  "requestLogs.detail.copy": "Copy all",
  "requestLogs.detail.noBody": "No further detail.",
  "requestLogs.detail.clientTool": "Client",
  "requestLogs.detail.clientVersion": "Client version",
  "requestLogs.detail.clientIp": "Caller IP",
  "requestLogs.detail.userAgent": "User-Agent",
  "requestLogs.detail.entryKind": "Entry endpoint",
  "requestLogs.detail.httpVersion": "Downstream HTTP",
  "requestLogs.client.unknown": "Unrecognized",
  "clientTool.claudeCode": "Claude Code",
  "clientTool.claudeDesktop": "Claude Desktop",
  "clientTool.codexCli": "Codex CLI",
  "clientTool.codexDesktop": "Codex Desktop",
  "clientTool.ccRouter": "cc-router (forwarded)",
  "clientTool.zed": "Zed",
  "clientTool.cursor": "Cursor",
  "clientTool.opencode": "OpenCode",
  "clientTool.anthropicSdkPython": "Anthropic Python SDK",
  "clientTool.anthropicSdkJs": "Anthropic JS SDK",

  "logs.tab.requests": "Requests",
  "logs.tab.subscriptionEvents": "Subscription events",
  "logs.tab.systemErrors": "System errors",
  "logs.subscriptionEvents.subtitle": "History of subscription state machine transitions—useful for tracing when a subscription started failing.",
  "logs.subscriptionEvents.empty": "No subscription state changes recorded yet.",
  "logs.systemErrors.subtitle": "System-level failures and aggregate 503s that don't map to a single request.",
  "logs.systemErrors.empty": "No system errors.",
  "logs.systemErrors.detailTitle": "System error detail",
  "logs.systemErrors.summary": "Summary",
  "logs.systemErrors.payload": "Context",

  "subscriptions.title": "Subscriptions",
  "subscriptions.subtitle": "Each subscription is one vendor's API key. Status reflects health checks live.",
  "subscriptions.add": "Add subscription",
  "subscriptions.empty.message": "No subscriptions yet. Click \"Add subscription\" to get started.",
  "subscriptions.empty.action": "Add your first subscription",
  "subscriptions.col.status": "Status",
  "subscriptions.col.provider": "Provider",
  "subscriptions.col.note": "Note",
  "subscriptions.col.referenced": "Used by",
  "subscriptions.col.updatedAt": "Updated",
  "subscriptions.notUsed": "Unused",
  "subscriptions.custom": "Custom",
  "subscriptions.view": "View",

  "virtualModels.title": "Virtual models",
  "virtualModels.subtitle1": "Three fixed virtual models map to Claude Code's model slots; ",
  "virtualModels.subtitle2": " is the catch-all — any other model request goes here.",
  "virtualModels.endpointsSuffix": " endpoints",
  "virtualModels.mode.label": "Mode",
  "virtualModels.mode.sequentialHint": "By priority, fail over on error",
  "virtualModels.mode.roundRobinHint": "Even distribution, skip when rate-limited",
  "virtualModels.addButton": "Add subscription to this virtual model",
  "virtualModels.dialog.title": "Select subscriptions to add",
  "virtualModels.dialog.empty": "No available subscriptions. Add one in \"Subscriptions\" first.",
  "virtualModels.dialog.add": "Add selected",

  "subscriptionNew.back": "Back",
  "subscriptionNew.backToList": "Back to list",
  "subscriptionNew.welcomeTitle": "Welcome to cc-router",
  "subscriptionNew.title": "Add subscription",
  "subscriptionNew.welcomeSubtitle": "Add your first subscription. We'll bind it to all 4 virtual models and jump to the setup guide.",
  "subscriptionNew.subtitle": "Connect a vendor's API key to the router and bind it to virtual model slots.",
  "subscriptionNew.step1": "Basic info",
  "subscriptionNew.step2": "Bind models",
  "subscriptionNew.field.provider": "Provider",
  "subscriptionNew.providerSelect": "Select provider",
  "subscriptionNew.customProvider": "Custom (Anthropic compatible)",
  "subscriptionNew.group.firstParty": "Providers",
  "subscriptionNew.group.secondParty": "AI apps",
  "subscriptionNew.group.aggregator": "API aggregators",
  "subscriptionNew.group.custom": "Custom",
  "subscriptionNew.customHint": "Custom path: fill in connection info and model slots in one page, no two-step wizard.",
  "subscriptionNew.customGeminiProvider": "Custom (Gemini compatible)",
  "subscriptionNew.customGeminiHint": "Use this for Google AI Studio or any Gemini-compatible relay. cc-router translates Anthropic Messages calls into Gemini generateContent automatically.",
  "subscriptionNew.geminiBaseUrlHint": "Gemini endpoint domain root. Use https://generativelanguage.googleapis.com for AI Studio, or your relay's actual domain.",
  "subscriptionNew.geminiMessagesPathHint": "URL path template. Must contain the {model} placeholder — cc-router substitutes it with the slot's real model name per request.",
  "subscriptionNew.geminiAuthLocked": "Gemini endpoints always use the x-goog-api-key header. Just paste your API key, no auth method to pick.",
  "subscriptionNew.customOpenaiProvider": "Custom (OpenAI Responses compatible)",
  "subscriptionNew.customOpenaiHint": "Use this for the official OpenAI /v1/responses endpoint or any OpenAI-compatible relay (one-api, new-api, etc.). cc-router translates Anthropic Messages into OpenAI Responses calls and supports multi-turn reasoning replay.",
  "subscriptionNew.openaiAuthLocked": "OpenAI Responses endpoints always use Authorization: Bearer. Just paste your API key (usually starts with sk-...), no auth method to pick.",
  "subscriptionNew.openaiBaseUrlHint": "OpenAI Responses endpoint domain root. Use https://api.openai.com for the official API, or your relay's actual domain.",
  "subscriptionNew.openaiMessagesPathHint": "URL path, usually /v1/responses. Relays may use a different path — check their docs.",
  "subscriptionNew.customOpenaiChatProvider": "Custom (OpenAI Chat Completions compatible)",
  "subscriptionNew.customOpenaiChatHint": "Use this for OpenAI /v1/chat/completions compatible services: DeepSeek, Together, Groq, Ollama, any one-api / new-api relay, and OpenAI's legacy models (GPT-4 / 4-turbo). cc-router translates Anthropic Messages into Chat Completions calls automatically, and surfaces DeepSeek R1's reasoning_content as Claude Code thinking blocks.",
  "subscriptionNew.openaiChatBaseUrlHint": "Chat Completions endpoint domain root. Examples: OpenAI https://api.openai.com, DeepSeek https://api.deepseek.com, Together https://api.together.xyz, Groq https://api.groq.com/openai, Ollama http://localhost:11434.",
  "subscriptionNew.openaiChatMessagesPathHint": "URL path, usually /v1/chat/completions. Relays may use a different path — check their docs.",
  "subscriptionNew.openaiChatAuthLocked": "OpenAI Chat Completions endpoints always use Authorization: Bearer. Just paste your API key (usually starts with sk-...; for auth-free setups like Ollama, any non-empty string works), no auth method to pick.",
  "subscriptionNew.errGeminiPathPlaceholder": "Gemini path template must contain the {model} placeholder",
  "subscriptionNew.field.endpoint": "Endpoint",
  "subscriptionNew.endpointSelect": "Select endpoint",
  "subscriptionNew.openApiKey": "Get API key from website",
  "subscriptionNew.field.providerName": "Provider display name",
  "subscriptionNew.providerNameHint": "Name shown in the dropdown — editable later.",
  "subscriptionNew.providerNamePh": "e.g. My self-hosted gateway",
  "subscriptionNew.baseUrlHint": "Domain root only — do not include the /v1/messages path.",
  "subscriptionNew.messagesPathHint": "Usually /v1/messages. Some proxies use a different path.",
  "subscriptionNew.authMethod": "Authentication",
  "subscriptionNew.field.note": "Note",
  "subscriptionNew.notePh": "e.g. My MiniMax account",
  "subscriptionNew.noteHint": "Local label only — never uploaded anywhere.",
  "subscriptionNew.slotsLabel": "Virtual model slots",
  "subscriptionNew.slotsHint": "These three slots determine which real model strings cc-router routes model-opus / model-sonnet / model-haiku to.",
  "subscriptionNew.errFillProvider": "Please enter the provider display name",
  "subscriptionNew.errFillBase": "Please enter the base URL",
  "subscriptionNew.errFillKey": "Please enter the API key",
  "subscriptionNew.errFillNote": "Please enter a note for the subscription",
  "subscriptionNew.errFillSlots": "Please fill in all three virtual model slot real model names",
  "subscriptionNew.errCreate": "Create failed",
  "subscriptionNew.slotPh": "e.g. claude-3-5-sonnet-20241022",
  "subscriptionNew.field.chatgptAccount": "ChatGPT account",
  "oauth.chatgpt.title": "Connect ChatGPT account",
  "oauth.chatgpt.subtitle": "Use the Codex quota of your ChatGPT Plus/Pro subscription. Authorization is independent from the Codex CLI and stored only inside cc-router.",
  "oauth.chatgpt.starting": "Initializing login link…",
  "oauth.chatgpt.instructions": "Browser opened. Please confirm the code shown on the page matches the one below, then authorize.",
  "oauth.chatgpt.userCodeLabel": "User code",
  "oauth.chatgpt.openBrowser": "Reopen browser",
  "oauth.chatgpt.waitingForAuth": "Waiting for you to authorize in the browser…",
  "oauth.chatgpt.connected": "Connected",
  "oauth.chatgpt.failed": "Login failed, please try again",
  "oauth.chatgpt.noEmail": "ChatGPT account",
  "oauth.chatgpt.reconnect": "Switch account",
  "oauth.chatgpt.connectButton": "Connect ChatGPT account",
  "oauth.chatgpt.connectHint": "After authorization, cc-router will run Claude Code using your ChatGPT subscription quota. Your local Codex CLI is not affected.",
  "oauth.chatgpt.tosWarning": "⚠️ ChatGPT subscriptions are intended for OpenAI's own products and the Codex CLI; third-party usage is a gray area and OpenAI reserves the right to apply account controls. Tips: use a secondary account; avoid bursty high-frequency calls; phone-number verification when authorizing a new device is the standard flow.",
  "subscriptionNew.field.kiroCredential": "Kiro credential",
  "oauth.kiro.title": "Connect Kiro account",
  "oauth.kiro.subtitle": "Use the free Claude quota from Kiro IDE (backed by AWS CodeWhisperer).",
  "oauth.kiro.tosWarning": "⚠️ Kiro subscriptions are intended for Kiro IDE / kiro-cli usage; third-party access is a gray area and AWS reserves the right to apply account controls. Tips: avoid bursty high-frequency calls; phone-number verification when authorizing a new device is the standard flow.",
  "oauth.kiro.tabImport": "Import from JSON",
  "oauth.kiro.tabDeviceFlow": "AWS Builder ID login",
  "oauth.kiro.importDescription": "If you have logged in to Kiro IDE or run kiro-cli login, your credentials are already cached under ~/.aws/sso/cache/ and can be loaded directly.",
  "oauth.kiro.localFilePath": "Local credential file path",
  "oauth.kiro.readFile": "Read",
  "oauth.kiro.importPasted": "Import pasted credential",
  "oauth.kiro.deviceFlowDescription": "Use AWS SSO OIDC Device Flow to complete Builder ID authorization in your browser (a free account is enough). On success cc-router receives the refresh_token automatically; it never enters JS.",
  "oauth.kiro.startBuilderIdLogin": "Start AWS Builder ID login",
  "oauth.kiro.importing": "Parsing credential…",
  "oauth.kiro.deviceStarting": "Initializing login link…",
  "oauth.kiro.deviceInstructions": "Browser opened. Please confirm the code shown on the page matches the one below, then authorize.",
  "oauth.kiro.userCodeLabel": "User code",
  "oauth.kiro.openBrowser": "Reopen browser",
  "oauth.kiro.waitingForAuth": "Waiting for you to authorize in the browser…",
  "oauth.kiro.connected": "Connected",
  "oauth.kiro.failed": "Login failed, please try again",
  "oauth.kiro.reconnect": "Use a different credential",
  "oauth.kiro.connectButton": "Connect Kiro credential",
  "oauth.kiro.connectHint": "Supports either importing Kiro IDE's cached JSON or AWS Builder ID OAuth. After import you still need to confirm 4 disguise fields.",
  "oauth.kiro.credentialReady": "Credential ready",
  "oauth.kiro.authMethod": "Auth method",
  "oauth.kiro.profileArnDetected": "✓ profileArn detected, will be injected on each request.",
  "oauth.kiro.disguiseTitle": "Request disguise fields",
  "oauth.kiro.disguiseHint": "These fields are sent to AWS together with the user-agent / x-amz-user-agent header on every request, mimicking a Kiro IDE client. Defaults follow cc-router upgrades; you can edit them manually (e.g. copy the real IDE's machineId to further reduce risk-control friction).",
  "oauth.kiro.regen": "Regenerate",
  "oauth.kiro.confirmAndNext": "Confirm and continue",
  "oauth.kiro.errPasteEmpty": "Please paste the credential JSON",
  "oauth.kiro.sourceFromJson": "From JSON import",
  "oauth.kiro.sourceFromDeviceFlow": "From AWS Builder ID login",
  "common.orPasteBelow": "Or paste JSON",
  "common.retry": "Retry",

  "subscriptionEdit.notFound": "Subscription not found",
  "subscriptionEdit.referencedPrefix": "Used by: ",
  "subscriptionEdit.enabled": "Enabled",
  "subscriptionEdit.basicInfo": "Basic info",
  "subscriptionEdit.providerLocked": "(locked)",
  "subscriptionEdit.endpointChangeWarn": "Saving will re-copy connection info from this endpoint template",
  "subscriptionEdit.providerNamePh": "Provider display name",
  "subscriptionEdit.authHeaderName": "Auth header name",
  "subscriptionEdit.authHeaderNamePh": "Authorization or x-api-key",
  "subscriptionEdit.authHeaderFormat": "Auth format",
  "subscriptionEdit.authBearerOption": "Bearer (prepends \"Bearer \" to header value)",
  "subscriptionEdit.authRawOption": "Raw (uses key as-is)",
  "subscriptionEdit.modelSlotsTitle": "Model slots",
  "subscriptionEdit.modelCacheUpdated": "Models updated: ",
  "subscriptionEdit.testModel": "Test model: ",
  "subscriptionEdit.stateReset": "✓ Subscription state reset to healthy",
  "subscriptionEdit.testConn": "Test connection",
  "subscriptionEdit.errSave": "Save failed",
  "subscriptionEdit.keyDialog.title": "Update API key",
  "subscriptionEdit.keyDialog.desc": "The new key takes effect immediately.",
  "subscriptionEdit.keyDialog.placeholder": "New API key",
  "subscriptionEdit.deleteDialog.titlePrefix": "Delete \"",
  "subscriptionEdit.deleteDialog.titleSuffix": "\"?",
  "subscriptionEdit.deleteDialog.refByPrefix": "This subscription is used by ",
  "subscriptionEdit.deleteDialog.refBySuffix": " virtual model(s):",
  "subscriptionEdit.deleteDialog.refByOutro": "After deletion these virtual models will lose this subscription.",
  "subscriptionEdit.deleteDialog.noRef": "Deleting a subscription also removes the stored API key.",
  "subscriptionEdit.deleteDialog.confirm": "Confirm delete",

  "common.relativeTime.justNow": "Just now",
  "common.relativeTime.minutesAgo": " minutes ago",
  "common.relativeTime.hoursAgo": " hours ago",
  "common.relativeTime.daysAgo": " days ago",

  "subscriptionBalance.title": "Balance",
  "subscriptionBalance.refresh": "Refresh balance",
  "subscriptionBalance.refreshing": "Loading…",
  "subscriptionBalance.lastUpdatedPrefix": "Last updated ",
  "subscriptionBalance.neverFetched": "Not fetched yet — click the button to load the latest balance",
  "subscriptionBalance.errPrefix": "Balance query failed: ",
  "subscriptionBalance.accountUnavailable": "Account is currently unavailable (out of credit or restricted)",
  "subscriptionBalance.severityLow": "Balance is low",
  "subscriptionBalance.severityCritical": "Balance is critical",

  "modelSlot.label": "Model slots",
  "modelSlot.modeAuto": "Auto",
  "modelSlot.modeManual": "Manual",
  "modelSlot.refresh": "Refresh model list",
  "modelSlot.errPrefix": "Failed to fetch model list: ",
  "modelSlot.errSuffix": ". Switched to manual input.",
  "modelSlot.examplePrefix": "Examples: ",
  "modelSlot.opus.label": "Opus slot",
  "modelSlot.opus.hint": "Advanced tasks / Plan Mode",
  "modelSlot.sonnet.label": "Sonnet slot",
  "modelSlot.sonnet.hint": "Default chat",
  "modelSlot.haiku.label": "Haiku slot",
  "modelSlot.haiku.hint": "Small tasks / tool calls",
  "modelSlot.placeholder": "Select a model",
  "modelSlot.historicalSuffix": " (historical)",
  "modelSlot.historicalTitle": "{model} is not in the auto list — it may be a previously manual entry. Switch to manual mode to change it.",
  "modelSlot.modelIdPh": "Enter the model ID provided by the vendor",

  "providerBadge.verified": "Verified",
  "providerBadge.partial": "Partial",
  "providerBadge.untested": "Untested",

  "routeFlow.title": "Route map",
  "routeFlow.live": "Live",
  "routeFlow.offline": "Offline",
  "routeFlow.notBound": "Not bound",
  "routeFlow.providersTitle": "Vendor subscriptions",
  "routeFlow.providersEmpty": "No subscriptions bound",

  "sortableSub.empty": "No subscriptions. Click the button below to add.",
  "sortableSub.passthrough": "Passes the request model through unchanged",
  "sortableSub.dragHandle": "Drag to reorder",
  "sortableSub.remove": "Remove",

  "subscriptionState.healthy": "Healthy",
  "subscriptionState.rate_limited": "Rate limited",
  "subscriptionState.quota_exhausted": "Quota exhausted",
  "subscriptionState.transient_error": "Transient error",
  "subscriptionState.auth_failed": "Auth failed",
  "subscriptionState.disabled": "Disabled",

  "copyable.copied": "Copied",
  "copyable.copy": "Copy",

  "vm.opus.purpose": "Advanced tasks",
  "vm.opus.purposeEn": "Plan Mode",
  "vm.opus.label": "Advanced · Plan Mode",
  "vm.sonnet.purpose": "Default chat",
  "vm.sonnet.purposeEn": "Default chat",
  "vm.sonnet.label": "Default chat",
  "vm.haiku.purpose": "Small tasks",
  "vm.haiku.purposeEn": "Tool calls",
  "vm.haiku.label": "Small tasks · Tool calls",
  "vm.fallback.purpose": "Fallback",
  "vm.fallback.purposeEn": "Unknown models",
  "vm.fallback.label": "Fallback · pass-through unknown models",
  "vm.mode.sequential": "Sequential",
  "vm.mode.round_robin": "Round-robin",

  "validation.baseUrl": "Base URL must start with http:// or https://",
  "validation.messagesPath": "Messages path must start with /",

  "sidebar.nav.receipts": "Receipts",

  "receipts.title": "Receipts",
  "receipts.subtitle": "Render your subscription token usage as a shareable receipt-style snapshot. Pricing is hidden by default — only usage is shown.",
  "receipts.empty": "No requests in this period.",
  "receipts.loadError": "Failed to load receipt data",
  "receipts.exportFailed": "Export failed, please try again.",
  "receipts.savedToDownloads": "Saved to Downloads folder",
  "receipts.openDownloads": "Open",

  "receipts.range.last24h": "Last 24 hours",
  "receipts.range.last7": "Last 7 days",
  "receipts.range.last30": "Last 30 days",
  "receipts.range.lastYear": "Last year",
  "receipts.range.all": "All time",

  "receipts.controls.range.title": "Time range",
  "receipts.controls.display.title": "Display options",
  "receipts.controls.display.colorMode": "Color mode",
  "receipts.controls.display.colorModeDesc": "Default is monochrome (printed-receipt look). Toggle on for cream paper with dark-brown ink.",
  "receipts.controls.display.showProviderLogo": "Show provider logo",
  "receipts.controls.display.showProviderLogoDesc": "Add brand icons (Anthropic / DeepSeek / Zhipu, etc.) before the provider name on each sub-item row. Auto-grayscaled in monochrome mode.",
  "receipts.controls.display.showCache": "Show cache tokens",
  "receipts.controls.display.showCacheDesc": "Hide to keep only the input / output rows for a cleaner slip.",
  "receipts.controls.display.showCounts": "Show request counts",
  "receipts.controls.display.showCountsDesc": "Hide to show only token counts; the \"156×\" suffix on each item disappears.",
  "receipts.controls.display.compactTokens": "Compact numbers (K/M)",
  "receipts.controls.display.compactTokensDesc": "Compress token numbers into K/M form (e.g. 12.35K, 1.23M); values below 1000 stay as-is.",
  "receipts.controls.display.groupMode.label": "View mode",
  "receipts.controls.display.groupMode.virtual_model": "By virtual model",
  "receipts.controls.display.groupMode.subscription": "By subscription",
  "receipts.controls.display.groupMode.totals_only": "Totals only",
  "receipts.controls.display.groupMode.desc": "Switch the slip body's aggregation dimension; By subscription / Totals only no longer group by virtual-model slot.",
  "receipts.controls.filter.title": "Filters",
  "receipts.controls.filter.bySubscription": "By subscription",
  "receipts.controls.filter.byProvider": "By provider",
  "receipts.controls.filter.allSubscriptions": "All subscriptions",
  "receipts.controls.filter.allProviders": "All providers",
  "receipts.controls.filter.excludeDeleted": "Exclude deleted subscriptions",
  "receipts.controls.filter.excludeDeletedDesc": "When checked, the receipt hides usage from subscriptions that have been deleted; totals recalculate automatically.",
  "receipts.controls.export.title": "Export receipt",
  "receipts.controls.export.png": "PNG",
  "receipts.controls.export.pdf": "PDF",
  "receipts.controls.export.html": "HTML",
  "receipts.controls.export.exporting": "Exporting…",

  "receipts.slip.header": "USAGE SLIP",
  "receipts.slip.tagline": "Multi-subscription · Anthropic Messages endpoint",
  "receipts.slip.period": "Period",
  "receipts.slip.issued": "Issued",
  "receipts.slip.slipNo": "Slip No.",
  "receipts.slip.totalRequests": "TOTAL REQUESTS",
  "receipts.slip.totalTokens": "TOTAL TOKENS",
  "receipts.slip.input": "input",
  "receipts.slip.output": "output",
  "receipts.slip.cacheCreate": "cache create",
  "receipts.slip.cacheRead": "cache read",
  "receipts.slip.subtotal": "subtotal",
  "receipts.slip.empty": "(no requests)",
  "receipts.slip.deletedSub": "(deleted subscription)",
  "receipts.slip.thanks": "Thanks for routing with cc-router",
  "receipts.slip.section.bySubscription": "By subscription",
  "receipts.slip.section.byRealModel": "By real model"
}
