فهرست منبع

PR:i18n settings 拆分与翻译质量门禁 (#588)

* refactor(i18n): split settings json into smaller files

* refactor(i18n): load settings from split module

* refactor(i18n): remove legacy settings.json

* chore(i18n): update sync-settings-keys for split layout

* test(i18n): add split settings guards

* chore: align biome schema version

* chore(i18n): document messages loading contract

* chore(i18n): add settings split verification notes

* chore: format code (refactor-i18n-split-settings-3f48fec)

* chore: fix i18n request formatting

* chore: format code (refactor-i18n-split-settings-a1eff62)

* fix: replace settings placeholder translations

* chore: verify settings sync script is idempotent

* test: run i18n settings split guards

* test: add audit for zh-CN placeholder settings strings

* chore: apply biome formatting

* chore: document manual i18n settings verification

* fix: translate all providers filter in ja

* fix: translate all providers filter in zh-TW

* fix: translate providers section copy in zh-TW

* fix: translate providers section copy in ja

* feat: extend placeholder audit output

* feat: add allowlist for placeholder audit

* docs: define i18n translation quality rules

* chore: add i18n audit fail commands

* docs: add i18n PR checklist

* chore: format i18n audit tests

* fix: translate dashboard placeholders

* fix: translate myUsage placeholders

* fix: enforce locale-specific parentheses

* fix: start translating provider form strings

* fix: translate provider form strings

* fix: translate provider guide content

* test: add ja dashboard parentheses guard

* test: add zh-TW dashboard parentheses guard

* test: add zh-TW myUsage parentheses guard

* chore: translate ja provider form strings

* chore: translate zh-TW provider form strings

* chore: translate ja providers guide

* chore: translate zh-TW providers guide

* chore: refine zh-TW dashboard strings

* chore: translate ja providers strings

* chore: translate zh-TW providers strings

* chore: refine zh-TW api test strings

* chore: translate zh-TW settings small modules

* chore: translate ja settings small modules

* chore: clear i18n placeholders in settings

* chore: format code (refactor-i18n-split-settings-2437d19)

* test: fix biome formatting in i18n test

* chore: verify Biome lint gate (I18NE-030)

* chore: add messages emoji audit script (I18NE-010)

* fix: remove emoji from messages warnings (I18NE-040)

* test: add messages no-emoji audit gate (I18NE-050)

* docs: add zh-CN i18n docs (I18NE-020)

* docs: add messages no-emoji rule (I18NE-060)

* chore: run full regression checks (I18NE-070)

* docs: add i18n PR evidence template (I18NE-080)

* fix: make messages no-emoji audit path-sep safe

* docs: add bun alias for messages no-emoji audit

* fix: detect keycap and flag emoji sequences in i18n message audits
YangQing-Lin 1 ماه پیش
والد
کامیت
8637837f09
100فایلهای تغییر یافته به همراه4699 افزوده شده و 4361 حذف شده
  1. 6 0
      CONTRIBUTING.md
  2. 1 1
      biome.json
  3. 36 0
      docs/i18n-pr-checklist.md
  4. 36 0
      docs/i18n-pr-checklist.zh-CN.md
  5. 68 0
      docs/i18n-pr-evidence-2026-01-11.md
  6. 37 0
      docs/i18n-settings-split.md
  7. 39 0
      docs/i18n-settings-split.zh-CN.md
  8. 64 0
      docs/i18n-translation-quality.md
  9. 64 0
      docs/i18n-translation-quality.zh-CN.md
  10. 1 1
      messages/en/index.ts
  11. 2 2
      messages/en/provider-chain.json
  12. 0 2176
      messages/en/settings.json
  13. 51 0
      messages/en/settings/clientVersions.json
  14. 31 0
      messages/en/settings/common.json
  15. 89 0
      messages/en/settings/config.json
  16. 133 0
      messages/en/settings/data.json
  17. 157 0
      messages/en/settings/errorRules.json
  18. 17 0
      messages/en/settings/errors.json
  19. 101 0
      messages/en/settings/index.ts
  20. 54 0
      messages/en/settings/logs.json
  21. 15 0
      messages/en/settings/nav.json
  22. 146 0
      messages/en/settings/notifications.json
  23. 191 0
      messages/en/settings/prices.json
  24. 16 0
      messages/en/settings/providers/autoSort.json
  25. 13 0
      messages/en/settings/providers/filter.json
  26. 157 0
      messages/en/settings/providers/form/apiTest.json
  27. 9 0
      messages/en/settings/providers/form/buttons.json
  28. 3 0
      messages/en/settings/providers/form/common.json
  29. 6 0
      messages/en/settings/providers/form/deleteDialog.json
  30. 8 0
      messages/en/settings/providers/form/errors.json
  31. 13 0
      messages/en/settings/providers/form/failureThresholdConfirmDialog.json
  32. 7 0
      messages/en/settings/providers/form/key.json
  33. 5 0
      messages/en/settings/providers/form/maxRetryAttempts.json
  34. 14 0
      messages/en/settings/providers/form/modelRedirect.json
  35. 20 0
      messages/en/settings/providers/form/modelSelect.json
  36. 4 0
      messages/en/settings/providers/form/name.json
  37. 10 0
      messages/en/settings/providers/form/providerTypes.json
  38. 21 0
      messages/en/settings/providers/form/proxyTest.json
  39. 313 0
      messages/en/settings/providers/form/sections.json
  40. 204 0
      messages/en/settings/providers/form/strings.json
  41. 4 0
      messages/en/settings/providers/form/success.json
  42. 4 0
      messages/en/settings/providers/form/title.json
  43. 4 0
      messages/en/settings/providers/form/url.json
  44. 9 0
      messages/en/settings/providers/form/urlPreview.json
  45. 5 0
      messages/en/settings/providers/form/websiteUrl.json
  46. 120 0
      messages/en/settings/providers/guide.json
  47. 12 0
      messages/en/settings/providers/inlineEdit.json
  48. 37 0
      messages/en/settings/providers/list.json
  49. 9 0
      messages/en/settings/providers/schedulingDialog.json
  50. 7 0
      messages/en/settings/providers/search.json
  51. 5 0
      messages/en/settings/providers/section.json
  52. 8 0
      messages/en/settings/providers/sort.json
  53. 47 0
      messages/en/settings/providers/strings.json
  54. 26 0
      messages/en/settings/providers/types.json
  55. 84 0
      messages/en/settings/requestFilters.json
  56. 55 0
      messages/en/settings/sensitiveWords.json
  57. 22 0
      messages/en/settings/strings.json
  58. 52 52
      messages/ja/dashboard.json
  59. 1 1
      messages/ja/index.ts
  60. 2 2
      messages/ja/provider-chain.json
  61. 0 2126
      messages/ja/settings.json
  62. 51 0
      messages/ja/settings/clientVersions.json
  63. 31 0
      messages/ja/settings/common.json
  64. 89 0
      messages/ja/settings/config.json
  65. 133 0
      messages/ja/settings/data.json
  66. 157 0
      messages/ja/settings/errorRules.json
  67. 17 0
      messages/ja/settings/errors.json
  68. 101 0
      messages/ja/settings/index.ts
  69. 54 0
      messages/ja/settings/logs.json
  70. 15 0
      messages/ja/settings/nav.json
  71. 146 0
      messages/ja/settings/notifications.json
  72. 191 0
      messages/ja/settings/prices.json
  73. 16 0
      messages/ja/settings/providers/autoSort.json
  74. 13 0
      messages/ja/settings/providers/filter.json
  75. 157 0
      messages/ja/settings/providers/form/apiTest.json
  76. 9 0
      messages/ja/settings/providers/form/buttons.json
  77. 3 0
      messages/ja/settings/providers/form/common.json
  78. 6 0
      messages/ja/settings/providers/form/deleteDialog.json
  79. 8 0
      messages/ja/settings/providers/form/errors.json
  80. 13 0
      messages/ja/settings/providers/form/failureThresholdConfirmDialog.json
  81. 7 0
      messages/ja/settings/providers/form/key.json
  82. 5 0
      messages/ja/settings/providers/form/maxRetryAttempts.json
  83. 14 0
      messages/ja/settings/providers/form/modelRedirect.json
  84. 20 0
      messages/ja/settings/providers/form/modelSelect.json
  85. 4 0
      messages/ja/settings/providers/form/name.json
  86. 10 0
      messages/ja/settings/providers/form/providerTypes.json
  87. 21 0
      messages/ja/settings/providers/form/proxyTest.json
  88. 313 0
      messages/ja/settings/providers/form/sections.json
  89. 204 0
      messages/ja/settings/providers/form/strings.json
  90. 4 0
      messages/ja/settings/providers/form/success.json
  91. 4 0
      messages/ja/settings/providers/form/title.json
  92. 4 0
      messages/ja/settings/providers/form/url.json
  93. 9 0
      messages/ja/settings/providers/form/urlPreview.json
  94. 5 0
      messages/ja/settings/providers/form/websiteUrl.json
  95. 120 0
      messages/ja/settings/providers/guide.json
  96. 12 0
      messages/ja/settings/providers/inlineEdit.json
  97. 37 0
      messages/ja/settings/providers/list.json
  98. 9 0
      messages/ja/settings/providers/schedulingDialog.json
  99. 7 0
      messages/ja/settings/providers/search.json
  100. 5 0
      messages/ja/settings/providers/section.json

+ 6 - 0
CONTRIBUTING.md

@@ -112,6 +112,12 @@ bun run typecheck
 # 如果更改影响运行逻辑,执行端到端验证或 bun run test
 ```
 
+### i18n 变更(翻译质量/抽查)
+
+如果 PR 涉及 i18n 文案(尤其是 `settings` / `dashboard` / `myUsage`),请遵循:
+- 规则说明:`docs/i18n-translation-quality.md`
+- PR Checklist:`docs/i18n-pr-checklist.md`
+
 CI 会在 PR 上运行 `Docker Build Test`(见 `.github/CI_CD_SETUP.md`)。如需验证容器构建,可本地执行:
 
 ```bash

+ 1 - 1
biome.json

@@ -1,5 +1,5 @@
 {
-  "$schema": "https://biomejs.dev/schemas/2.3.10/schema.json",
+  "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
   "vcs": {
     "enabled": true,
     "clientKind": "git",

+ 36 - 0
docs/i18n-pr-checklist.md

@@ -0,0 +1,36 @@
+# i18n PR checklist
+
+> 中文对照版: [i18n-pr-checklist.zh-CN.md](i18n-pr-checklist.zh-CN.md)
+
+This checklist is for changes that affect i18n messages, especially `settings`, `dashboard`, and `myUsage`.
+
+## Required (automation)
+
+- [ ] Run placeholder audit (scoped):
+  - `bun run i18n:audit-placeholders`
+- [ ] If the PR is meant to eliminate placeholders, ensure fail mode is clean:
+  - `bun run i18n:audit-placeholders:fail`
+- [ ] Run messages no-emoji audit (fail mode):
+  - `bun run i18n:audit-messages-no-emoji:fail`
+- [ ] Run unit tests relevant to i18n/settings split:
+  - `bunx vitest run tests/unit/i18n/settings-split-guards.test.ts`
+  - `bunx vitest run tests/unit/i18n/settings-index-modules-load.test.ts`
+
+## Required (review evidence)
+
+- [ ] Include in PR description:
+  - the audit output diff (before/after) or a short summary (counts by locale + key modules)
+  - any allowlist changes with reasons (keep allowlist minimal and auditable)
+
+## Required (manual spotcheck)
+
+For at least `ja` and `zh-TW`:
+- [ ] Settings pages (key areas): provider list, provider form, request filters, notifications
+- [ ] Dashboard key widgets
+- [ ] My Usage page
+
+Attach screenshots (or provide a local path) for the key pages above.
+
+## Rules to follow
+
+See `docs/i18n-translation-quality.md` for R1/R2/R3 rules and allowlist conventions.

+ 36 - 0
docs/i18n-pr-checklist.zh-CN.md

@@ -0,0 +1,36 @@
+# i18n PR 检查清单
+
+> English: [i18n-pr-checklist.md](i18n-pr-checklist.md)
+
+此清单适用于会影响 i18n messages 的变更,尤其是 `settings`、`dashboard`、`myUsage`。
+
+## 必做(自动化)
+
+- [ ] 运行 placeholder 审计(scoped):
+  - `bun run i18n:audit-placeholders`
+- [ ] 若该 PR 目标是清零 placeholders,确保 fail 模式无命中:
+  - `bun run i18n:audit-placeholders:fail`
+- [ ] 运行 messages no-emoji 审计(fail 模式):
+  - `bun run i18n:audit-messages-no-emoji:fail`
+- [ ] 运行与 i18n/settings split 相关的单元测试:
+  - `bunx vitest run tests/unit/i18n/settings-split-guards.test.ts`
+  - `bunx vitest run tests/unit/i18n/settings-index-modules-load.test.ts`
+
+## 必做(Review 证据)
+
+- [ ] 在 PR 描述中包含:
+  - 审计输出 diff(before/after)或简短摘要(按 locale 统计 + 关键模块)
+  - 如有 allowlist 变更,说明原因(保持 allowlist 最小且可审计)
+
+## 必做(人工抽查)
+
+至少覆盖 `ja` 与 `zh-TW`:
+- [ ] Settings 页面(关键区域):provider list、provider form、request filters、notifications
+- [ ] Dashboard 关键组件
+- [ ] My Usage 页面
+
+为上述关键页面附上截图(或提供本地路径)。
+
+## 需要遵守的规则
+
+参见 `docs/i18n-translation-quality.md` 获取 R1/R2/R3 规则与 allowlist 约定。

+ 68 - 0
docs/i18n-pr-evidence-2026-01-11.md

@@ -0,0 +1,68 @@
+# i18n no-emoji / docs zh evidence (2026-01-11)
+
+This document is intended to be copy-pasted into a PR description.
+
+## Summary
+
+- Emoji cleanup (messages JSON):
+  - Before: 20 strings contained emoji (top files: `provider-chain.json`, `settings/data.json` across locales)
+  - After: 0 hits from `rg -n --pcre2 "\\p{Extended_Pictographic}" messages`
+- Placeholder audit (zh-CN equality placeholders): OK
+- Quality gates: `lint` / `typecheck` / `test` / `build` all pass
+
+## Emoji cleanup details (messages JSON)
+
+Key locations that were cleaned (keys unchanged, only values updated):
+- `messages/<locale>/provider-chain.json`
+  - `provider-chain.timeline.circuitTriggered`
+  - `provider-chain.timeline.systemErrorNote`
+- `messages/<locale>/settings/data.json`
+  - `settings.data.import.warningMerge`
+  - `settings.data.import.warningOverwrite`
+
+Commands:
+- Before/after scan:
+  - `rg -n --pcre2 "\\p{Extended_Pictographic}" messages`
+- Optional structured listing (prints masked preview, no emoji characters):
+  - `node scripts/audit-messages-emoji.js --format=tsv`
+
+## Placeholder audit (R1)
+
+- `bun run i18n:audit-placeholders:fail`
+- Expected output:
+  - `OK: no zh-CN placeholder candidates found in split settings.`
+
+## No-emoji gate (R4)
+
+- Script (codepoints only, no emoji printing):
+  - `bun run i18n:audit-messages-no-emoji:fail`
+- Regression test (part of `bun run test`):
+  - `tests/unit/i18n/audit-messages-no-emoji-script.test.ts`
+
+## Full regression commands
+
+- `bun run lint`
+- `bun run typecheck`
+- `bun run test`
+- `bun run build`
+
+## Related commits (local)
+
+- `564ab845` chore: add messages emoji audit script (I18NE-010)
+- `aaa9fc7d` fix: remove emoji from messages warnings (I18NE-040)
+- `80d20686` test: add messages no-emoji audit gate (I18NE-050)
+- `2ee38f59` docs: add zh-CN i18n docs (I18NE-020)
+- `44eeb5e9` docs: add messages no-emoji rule (I18NE-060)
+- `92ebaf0e` chore: run full regression checks (I18NE-070)
+
+## Manual spotcheck (ja / zh-TW)
+
+Due to environment limitations (no GUI/browser automation in this run), screenshots are not attached here.
+
+Recommended steps:
+1. Start dev server: `bun run dev` (port 13500)
+2. Open pages for both `ja` and `zh-TW` locales:
+   - Settings: `/settings` (providers list/form, request filters, notifications)
+   - Dashboard: `/dashboard` (key widgets)
+   - My Usage: `/my-usage`
+3. Attach screenshots to the PR (or provide local file paths) and label each with locale + route.

+ 37 - 0
docs/i18n-settings-split.md

@@ -0,0 +1,37 @@
+# i18n settings split
+
+> 中文对照版: [i18n-settings-split.zh-CN.md](i18n-settings-split.zh-CN.md)
+
+This repository splits `messages/<locale>/settings.json` into smaller JSON chunks under `messages/<locale>/settings/`.
+
+## Layout
+- `messages/<locale>/settings/*.json`: settings top-level object parts
+- `messages/<locale>/settings/strings.json`: top-level string keys that belong directly under `settings`
+- `messages/<locale>/settings/providers/*.json`: `settings.providers` object parts
+- `messages/<locale>/settings/providers/strings.json`: provider-level string keys
+- `messages/<locale>/settings/providers/form/*.json`: `settings.providers.form` object parts
+- `messages/<locale>/settings/providers/form/strings.json`: provider form string keys
+
+Runtime composition happens in `messages/<locale>/settings/index.ts` and is imported by `messages/<locale>/index.ts`.
+
+## Verification
+- Translation quality rules and audit commands:
+  - `docs/i18n-translation-quality.md`
+
+- Sync keys across locales (canonical: zh-CN):
+  - `node scripts/sync-settings-keys.js`
+
+- Unit tests:
+  - `bun run test`
+
+- Scoped coverage for split-related modules:
+  - `bunx vitest run --coverage --coverage.include=scripts/sync-settings-keys.js --coverage.include=messages/**/settings/index.ts`
+
+- Typecheck:
+  - `bun run typecheck`
+
+- Lint:
+  - `bun run lint`
+
+- Production build:
+  - `bun run build`

+ 39 - 0
docs/i18n-settings-split.zh-CN.md

@@ -0,0 +1,39 @@
+# i18n settings split(拆分说明)
+
+> English: [i18n-settings-split.md](i18n-settings-split.md)
+
+本仓库将 `messages/<locale>/settings.json` 拆分为更小的 JSON 文件,存放在 `messages/<locale>/settings/` 目录下。
+
+## 目录结构(Layout)
+
+- `messages/<locale>/settings/*.json`: settings 顶层对象的各个子模块
+- `messages/<locale>/settings/strings.json`: 直接属于 `settings` 顶层的字符串 key
+- `messages/<locale>/settings/providers/*.json`: `settings.providers` 对象拆分后的子模块
+- `messages/<locale>/settings/providers/strings.json`: provider 级别的字符串 key
+- `messages/<locale>/settings/providers/form/*.json`: `settings.providers.form` 对象拆分后的子模块
+- `messages/<locale>/settings/providers/form/strings.json`: provider form 的字符串 key
+
+运行时拼装发生在 `messages/<locale>/settings/index.ts`,并由 `messages/<locale>/index.ts` 引入。
+
+## 验证(Verification)
+
+- 翻译质量规则与审计命令:
+  - `docs/i18n-translation-quality.md`
+
+- 跨 locale 同步 key(canonical: zh-CN):
+  - `node scripts/sync-settings-keys.js`
+
+- 单元测试:
+  - `bun run test`
+
+- 针对 split 相关模块的 scoped coverage:
+  - `bunx vitest run --coverage --coverage.include=scripts/sync-settings-keys.js --coverage.include=messages/**/settings/index.ts`
+
+- Typecheck:
+  - `bun run typecheck`
+
+- Lint:
+  - `bun run lint`
+
+- Production build:
+  - `bun run build`

+ 64 - 0
docs/i18n-translation-quality.md

@@ -0,0 +1,64 @@
+# i18n translation quality rules (R1/R2/R3)
+
+> 中文对照版: [i18n-translation-quality.zh-CN.md](i18n-translation-quality.zh-CN.md)
+
+This document defines the **scope** and **executable rules** for i18n translation quality in this repo.
+Downstream scripts and review checklists should follow this document as the source of truth.
+
+## Scope
+
+Must-translate scope (at least):
+- `settings` (split settings messages under `messages/<locale>/settings/`)
+- `dashboard` (`messages/<locale>/dashboard.json`)
+- `myUsage` (`messages/<locale>/myUsage.json`)
+
+Locales: `zh-CN` is canonical. Other supported locales: `en`, `ja`, `ru`, `zh-TW`.
+
+## Rule R1: No zh-CN placeholders in non-canonical locales
+
+For any non-canonical locale:
+- If a leaf string **equals** the `zh-CN` leaf string at the same key path, and the `zh-CN` value contains Han characters, it is treated as a **placeholder candidate**.
+- Placeholder candidates should be **fixed** (translated), or **explicitly allowlisted** with a documented reason.
+
+Executable check:
+- `bun run i18n:audit-placeholders`
+- To fail the command on any findings: add `--fail`.
+  - `bun run i18n:audit-placeholders:fail`
+
+Allowlist (auditable, minimal):
+- `scripts/audit-settings-placeholders.allowlist.json`
+- Supported filters: `key`, `keyPrefix`, `keyRegex`, `valueRegex`, plus `glossary` terms.
+
+## Rule R2: Placeholders/tokens must be preserved
+
+When updating translations, **do not change**:
+- keys / JSON structure
+- placeholder tokens (e.g. `{name}`, `{count}`, `{resetTime}`)
+- URL / command snippets unless intentionally translated and verified safe
+
+Recommended verification:
+- unit tests under `tests/unit/i18n/`
+- spot-check affected UI pages for the locale (see the PR checklist)
+
+## Rule R3: Glossary and consistent terminology
+
+Maintain a short glossary for terms that should be consistent across locales (brand, model names, product terms).
+
+Initial glossary (expand as needed, but keep it minimal and reviewed):
+- Provider / Model / API / HTTP/2
+- Claude / OpenAI / Codex (names should not be translated)
+
+## Rule R4: No emoji in messages JSON
+
+`messages/**/*.json` must not contain emoji characters.
+
+Executable check:
+- `bun run i18n:audit-messages-no-emoji:fail`
+
+Notes:
+- The audit output prints file path + key path + Unicode codepoints (without printing emoji characters).
+
+## Notes
+
+- Prefer fixing translations over expanding allowlists.
+- Every allowlist entry must have a clear reason in the allowlist file (and ideally referenced in the PR description).

+ 64 - 0
docs/i18n-translation-quality.zh-CN.md

@@ -0,0 +1,64 @@
+# i18n 翻译质量规则(R1/R2/R3)
+
+> English: [i18n-translation-quality.md](i18n-translation-quality.md)
+
+本文档定义本仓库 i18n 翻译质量的 **scope** 与 **可执行规则**。
+下游脚本与 review checklist 应以本文档为真相源。
+
+## Scope
+
+必须翻译的范围(至少包含):
+- `settings`(拆分后的 settings messages,位于 `messages/<locale>/settings/`)
+- `dashboard`(`messages/<locale>/dashboard.json`)
+- `myUsage`(`messages/<locale>/myUsage.json`)
+
+Locales:`zh-CN` 为 canonical。其他支持的 locales:`en`、`ja`、`ru`、`zh-TW`。
+
+## Rule R1:非 canonical locale 禁止出现 zh-CN placeholder
+
+对于任意非 canonical locale:
+- 若某个 leaf string 在相同 key path 下 **等于** `zh-CN` 的 leaf string,且 `zh-CN` 的值包含汉字,则视为 **placeholder candidate**。
+- placeholder candidates 应被 **修复**(翻译),或以明确理由 **加入 allowlist**。
+
+可执行检查:
+- `bun run i18n:audit-placeholders`
+- 如需在任意命中时让命令失败:添加 `--fail`。
+  - `bun run i18n:audit-placeholders:fail`
+
+Allowlist(可审计、保持最小):
+- `scripts/audit-settings-placeholders.allowlist.json`
+- 支持的过滤器:`key`、`keyPrefix`、`keyRegex`、`valueRegex`,以及 `glossary` terms。
+
+## Rule R2:必须保留 placeholders/tokens
+
+更新翻译时,**不要改动**:
+- keys / JSON structure
+- placeholder tokens(例如 `{name}`、`{count}`、`{resetTime}`)
+- URL / command snippets(除非明确要翻译且已验证安全)
+
+建议的验证方式:
+- `tests/unit/i18n/` 下的单元测试
+- 对受影响 locale 的 UI 页面做 spot-check(见 PR checklist)
+
+## Rule R3:Glossary 与术语一致性
+
+维护一份简短 glossary,用于跨 locale 保持一致的术语(品牌、模型名、产品术语等)。
+
+初始 glossary(按需扩展,但保持最小并经过 review):
+- Provider / Model / API / HTTP/2
+- Claude / OpenAI / Codex(名称不翻译)
+
+## Rule R4:messages JSON 禁止 Emoji
+
+`messages/**/*.json` 中不允许出现 Emoji 字符。
+
+可执行检查:
+- `bun run i18n:audit-messages-no-emoji:fail`
+
+说明:
+- 审计输出包含文件路径 + key path + Unicode codepoints(不会直接打印 Emoji 字符本身)。
+
+## Notes
+
+- 优先修复翻译,而不是扩展 allowlists。
+- 每条 allowlist 记录都必须在 allowlist 文件中写清原因(最好在 PR 描述中也有引用)。

+ 1 - 1
messages/en/index.ts

@@ -11,7 +11,7 @@ import notifications from "./notifications.json";
 import providerChain from "./provider-chain.json";
 import providers from "./providers.json";
 import quota from "./quota.json";
-import settings from "./settings.json";
+import settings from "./settings";
 import ui from "./ui.json";
 import usage from "./usage.json";
 import users from "./users.json";

+ 2 - 2
messages/en/provider-chain.json

@@ -86,7 +86,7 @@
     "remaining": "{count} attempts remaining",
     "status": "Status",
     "alreadyBroken": "Circuit already broken",
-    "circuitTriggered": "⚠️ Circuit breaker triggered",
+    "circuitTriggered": "Warning: Circuit breaker triggered",
     "errorDetails": "Error Details",
     "systemError": "Network/System Error",
     "systemErrorFailed": "Network/System Error (Attempt {attempt})",
@@ -97,7 +97,7 @@
     "errorMeaning": "Meaning: {meaning}",
     "meaning": "Meaning",
     "notCountedInCircuit": "This error is not counted in provider circuit breaker",
-    "systemErrorNote": "ℹ️ This error is not counted in provider circuit breaker",
+    "systemErrorNote": "Note: This error is not counted in provider circuit breaker",
     "reselection": "Reselecting Provider",
     "reselect": "Reselecting Provider",
     "excluded": "Excluded: {providers}",

+ 0 - 2176
messages/en/settings.json

@@ -1,2176 +0,0 @@
-{
-  "clientVersions": {
-    "description": "Manage client version requirements to ensure users use latest stable version. VSCode plugin and CLI are managed separately.",
-    "empty": {
-      "description": "No active users using recognizable clients in past 7 days",
-      "title": "No client data available"
-    },
-    "features": {
-      "activeWindow": "Active Window: ",
-      "activeWindowDesc": "Only counts users with requests in the past 7 days",
-      "autoDetect": "System automatically detects the latest stable version (GA version) for each client type",
-      "blockOldVersion": "Users with old versions will receive HTTP 400 error and cannot continue using the service",
-      "errorMessage": "Error message includes current version and required upgrade version",
-      "gaRule": "GA Rule: ",
-      "gaRuleDesc": "A version is considered GA when used by more than 1 user",
-      "recommendation": "Recommendation: ",
-      "recommendationDesc": "Monitor the version distribution below and confirm new version stability before enabling.",
-      "title": "Feature Description",
-      "whatHappens": "What happens when enabled:"
-    },
-    "section": {
-      "distribution": {
-        "description": "Shows client version info for active users in past 7 days. Each client type independently tracks GA versions.",
-        "title": "Client Version Distribution"
-      },
-      "settings": {
-        "description": "When enabled, system automatically detects client version and blocks old version users.",
-        "title": "Update Reminder Settings"
-      }
-    },
-    "table": {
-      "currentGA": "Current GA Version: ",
-      "internalType": "Internal Type: ",
-      "lastActive": "Last Active",
-      "latest": "Latest",
-      "needsUpgrade": "Needs Upgrade",
-      "noUsers": "No user data available",
-      "status": "Status",
-      "unknown": "Unknown",
-      "user": "User",
-      "usersCount": "{count} users",
-      "version": "Current Version"
-    },
-    "title": "Client Update Reminder",
-    "toggle": {
-      "description": "When enabled, system will block requests from old version clients",
-      "disableSuccess": "Client version check disabled",
-      "enable": "Enable Update Reminder",
-      "enableSuccess": "Client version check enabled",
-      "toggleFailed": "Update failed"
-    }
-  },
-  "common": {
-    "cancel": "Cancel",
-    "completed": "Completed",
-    "confirm": "Confirm",
-    "copied": "Key copied to clipboard",
-    "copy": "Copy",
-    "copyFailed": "Copy failed",
-    "create": "Create",
-    "creating": "Creating...",
-    "delete": "Delete",
-    "disabled": "Disabled",
-    "edit": "Edit",
-    "empty": "No matching results found",
-    "enabled": "Enabled",
-    "error": "Unknown error",
-    "failed": "Failed",
-    "loading": "Loading...",
-    "none": "None (No users using this version)",
-    "refresh": "Refresh",
-    "reset": "Reset",
-    "save": "Save",
-    "saving": "Saving...",
-    "submit": "Submit",
-    "success": "Success",
-    "test": "Test",
-    "testing": "Testing...",
-    "unlimited": "Unlimited",
-    "unlimited_desc": "Unlimited",
-    "update": "Update",
-    "updating": "Updating..."
-  },
-  "config": {
-    "autoCleanup": "Auto Log Cleanup",
-    "autoCleanupDesc": "Automatically clean up historical log data on schedule to free up database storage space.",
-    "description": "Manage system basic parameters that affect site display and statistics behavior.",
-    "section": {
-      "siteParams": {
-        "title": "Site Parameters",
-        "description": "Configure site title, currency display unit, and dashboard statistics display policy."
-      },
-      "autoCleanup": {
-        "title": "Auto Log Cleanup",
-        "description": "Automatically clean up historical log data on schedule to free up database storage space."
-      }
-    },
-    "form": {
-      "allowGlobalView": "Allow Global Usage View",
-      "allowGlobalViewDesc": "When disabled, regular users can only view their own key usage statistics in the dashboard.",
-      "verboseProviderError": "Verbose Provider Error",
-      "verboseProviderErrorDesc": "When enabled, return detailed error messages when all providers are unavailable (including provider count, rate limit reasons, etc.); when disabled, only return a simple error code.",
-      "enableHttp2": "Enable HTTP/2",
-      "enableHttp2Desc": "When enabled, proxy requests will prefer HTTP/2 protocol. Automatically falls back to HTTP/1.1 on failure.",
-      "interceptAnthropicWarmupRequests": "Intercept Warmup Requests (Anthropic)",
-      "interceptAnthropicWarmupRequestsDesc": "When enabled, Claude Code warmup probe requests will be answered by CCH directly to avoid upstream provider calls; the request is logged for audit but is not billed, not rate-limited, and excluded from statistics.",
-      "enableThinkingSignatureRectifier": "Enable Thinking Signature Rectifier",
-      "enableThinkingSignatureRectifierDesc": "When Anthropic providers return thinking signature incompatibility or invalid request errors, automatically removes incompatible thinking blocks and retries once against the same provider (enabled by default).",
-      "enableResponseFixer": "Enable Response Fixer",
-      "enableResponseFixerDesc": "Automatically repairs common upstream response issues (encoding, SSE, truncated JSON). Enabled by default.",
-      "responseFixerFixEncoding": "Fix encoding issues",
-      "responseFixerFixEncodingDesc": "Removes BOM/null bytes and normalizes invalid UTF-8.",
-      "responseFixerFixSseFormat": "Fix SSE format",
-      "responseFixerFixSseFormatDesc": "Adds missing data: prefix, normalizes line endings, and fixes common field formatting.",
-      "responseFixerFixTruncatedJson": "Fix truncated JSON",
-      "responseFixerFixTruncatedJsonDesc": "Closes unclosed braces/quotes, removes trailing commas, and fills missing values with null when needed.",
-      "cleanupSchedule": "Cleanup Schedule",
-      "cleanupScheduleDesc": "Select the execution schedule for automatic cleanup",
-      "configUpdated": "System settings updated. The page will refresh to apply currency display changes.",
-      "currencyDisplay": "Currency Display Unit",
-      "currencyDisplayPlaceholder": "Select currency unit",
-      "currencyDisplayDesc": "After modification, all pages and API interfaces will use the corresponding currency symbol (symbol only, no exchange rate conversion).",
-      "keepDays": "Retention Days",
-      "keepDaysDesc": "Clean up logs older than this number of days",
-      "saveFailed": "Save failed",
-      "saveSuccess": "Saved successfully",
-      "saveError": "Save failed",
-      "saveSettings": "Save Settings",
-      "siteTitle": "Site Title",
-      "siteTitlePlaceholder": "e.g. Claude Code Hub",
-      "siteTitleRequired": "Site title cannot be empty",
-      "siteTitleDesc": "Used to set browser tab title and system default display name.",
-      "enableAutoCleanup": "Enable Auto Cleanup",
-      "enableAutoCleanupDesc": "Automatically clean up historical log data on schedule",
-      "cleanupRetentionDays": "Retention Days",
-      "cleanupRetentionDaysRequired": "Retention Days *",
-      "cleanupRetentionDaysPlaceholder": "30",
-      "cleanupRetentionDaysDesc": "Logs older than this number of days will be automatically cleaned (range: 1-365 days)",
-      "cleanupScheduleLabel": "Execution Time (Cron)",
-      "cleanupScheduleRequired": "Execution Time (Cron) *",
-      "cleanupSchedulePlaceholder": "0 2 * * *",
-      "cleanupScheduleCronDesc": "Cron expression, default: 0 2 * * * (2 AM daily)",
-      "cleanupScheduleCronExample": "Example: 0 3 * * 0 (3 AM every Sunday)",
-      "cleanupBatchSize": "Batch Size",
-      "cleanupBatchSizeRequired": "Batch Size *",
-      "cleanupBatchSizePlaceholder": "10000",
-      "cleanupBatchSizeDesc": "Number of records to delete per batch (range: 1000-100000, recommended 10000)",
-      "saveConfig": "Save Configuration",
-      "autoCleanupSaved": "Auto cleanup configuration saved",
-      "currencies": {
-        "USD": "$ US Dollar (USD)",
-        "CNY": "¥ Chinese Yuan (CNY)",
-        "EUR": "€ Euro (EUR)",
-        "JPY": "¥ Japanese Yen (JPY)",
-        "GBP": "£ British Pound (GBP)",
-        "HKD": "HK$ Hong Kong Dollar (HKD)",
-        "TWD": "NT$ New Taiwan Dollar (TWD)",
-        "KRW": "₩ South Korean Won (KRW)",
-        "SGD": "S$ Singapore Dollar (SGD)"
-      },
-      "billingModelSource": "Billing Model Source",
-      "billingModelSourcePlaceholder": "Select billing model source",
-      "billingModelSourceDesc": "Configure which model to use for billing when model redirection occurs. 'Before Redirection' uses the original model requested by the user, 'After Redirection' uses the actual model called.",
-      "billingModelSourceOptions": {
-        "original": "Before Redirection (Original Model)",
-        "redirected": "After Redirection (Actual Model)"
-      }
-    },
-    "siteSettings": "Site Parameters",
-    "siteSettingsDesc": "Configure site title, currency display unit, and dashboard statistics display policy.",
-    "title": "Basic Configuration"
-  },
-  "data": {
-    "cleanup": {
-      "rangeLabel": "Cleanup Range",
-      "range": {
-        "7days": "Logs older than 1 week (7 days)",
-        "30days": "Logs older than 1 month (30 days)",
-        "90days": "Logs older than 3 months (90 days)",
-        "180days": "Logs older than 6 months (180 days)"
-      },
-      "rangeDescription": {
-        "7days": "1 week ago",
-        "30days": "1 month ago",
-        "90days": "3 months ago",
-        "180days": "6 months ago",
-        "default": "{days} days ago"
-      },
-      "willClean": "Will clean all log records from {range}",
-      "button": "Clean Logs",
-      "confirmTitle": "Confirm Log Cleanup",
-      "confirmWarning": "This operation will permanently delete all log records from {range} and cannot be recovered.",
-      "previewLoading": "Counting...",
-      "previewCount": "Will delete {count} log records",
-      "previewError": "Unable to get preview",
-      "statisticsRetained": "✓ Statistics data will be retained (for trend analysis)",
-      "logsDeleted": "✗ Log details will be deleted (request/response content, error info, etc.)",
-      "backupRecommendation": "Recommendation: Export database backup before cleanup in case recovery is needed.",
-      "cancel": "Cancel",
-      "confirm": "Confirm Cleanup",
-      "cleaning": "Cleaning...",
-      "successMessage": "Successfully cleaned {count} log records ({batches} batches, took {duration}s)",
-      "failed": "Cleanup failed",
-      "error": "Failed to clean logs",
-      "descriptionWarning": "Clean up historical log data to free up database storage. Note: Statistics data will be retained, but log details will be permanently deleted."
-    },
-    "description": "Manage database backup and recovery with full data import/export and log cleanup.",
-    "export": {
-      "button": "Export Database",
-      "exporting": "Exporting...",
-      "successMessage": "Database exported successfully!",
-      "failed": "Export failed",
-      "error": "Failed to export database",
-      "descriptionFull": "Export complete database backup file (.dump format) for data migration or recovery. Backup uses PostgreSQL custom format, auto-compressed and compatible with different database versions."
-    },
-    "guide": {
-      "title": "Usage Instructions and Precautions",
-      "items": {
-        "cleanup": {
-          "title": "Log Cleanup",
-          "description": "Physically delete historical log data (irreversible). Statistics table will be retained. Recommend exporting database backup before cleanup."
-        },
-        "format": {
-          "title": "Backup Format",
-          "description": "Uses PostgreSQL custom format (.dump), auto-compressed and compatible with different database versions."
-        },
-        "overwrite": {
-          "title": "Overwrite Mode",
-          "description": "Deletes all existing data before importing, ensuring database matches backup exactly. Best for complete recovery."
-        },
-        "merge": {
-          "title": "Merge Mode",
-          "description": "Retains existing data and attempts to insert backup data. Primary key conflicts may cause import failure."
-        },
-        "safety": {
-          "title": "Security Recommendation",
-          "description": "Before importing, recommend exporting current database as backup to avoid data loss."
-        },
-        "environment": {
-          "title": "Environment Requirements",
-          "description": "This feature requires Docker Compose deployment. Local development may not support it."
-        }
-      }
-    },
-    "import": {
-      "selectFileLabel": "Select Backup File",
-      "fileSelected": "Selected: {name} ({size} MB)",
-      "fileError": "Please select .dump format backup file",
-      "noFileSelected": "Please select backup file first",
-      "cleanFirstLabel": "Clear existing data (overwrite mode)",
-      "cleanFirstDescription": "Delete all existing data before importing to ensure database matches backup exactly. If unchecked, will attempt to merge data but may fail due to primary key conflicts.",
-      "button": "Import Database",
-      "importing": "Importing...",
-      "progressTitle": "Import Progress",
-      "confirmTitle": "Confirm Database Import",
-      "confirmOverwrite": "You selected 'Overwrite Mode', which will delete all existing data before importing backup.",
-      "confirmMerge": "You selected 'Merge Mode', which will attempt to import backup while keeping existing data.",
-      "warningOverwrite": "⚠️ Warning: This action is irreversible, all current data will be permanently deleted!",
-      "warningMerge": "⚠️ Note: Import may fail if primary key conflicts exist.",
-      "backupFile": "Backup file:",
-      "backupRecommendation": "Recommend exporting current database as backup before proceeding.",
-      "cancel": "Cancel",
-      "confirm": "Confirm Import",
-      "successMessage": "Data import completed!",
-      "successCleanModeDesc": "All data has been successfully restored. Refresh your browser if the page displays incorrectly.",
-      "successMergeModeDesc": "Data has been successfully imported and merged. Refresh your browser if the page displays incorrectly.",
-      "successWithWarnings": "Data import completed (with warnings)",
-      "successWithWarningsDesc": "Data has been successfully imported, but some existing objects were skipped. Refresh your browser or restart the application if the page displays incorrectly.",
-      "failedMessage": "Data import failed",
-      "error": "Failed to import database",
-      "streamError": "Cannot read response stream",
-      "streamInterrupted": "Data stream unexpectedly interrupted",
-      "streamInterruptedDesc": "Import progress did not complete normally. Please check the logs and verify data integrity. Re-import if needed.",
-      "parseError": "Failed to parse response data",
-      "errorUnknown": "Unknown error",
-      "descriptionFull": "Restore database from backup file. Supports PostgreSQL custom format (.dump) backup files."
-    },
-    "status": {
-      "loading": "Loading...",
-      "error": "Failed to get database status",
-      "retry": "Retry",
-      "connected": "Database connected",
-      "unavailable": "Database unavailable",
-      "tables": "{count} tables"
-    },
-    "title": "Data Management",
-    "section": {
-      "status": {
-        "title": "Database Status",
-        "description": "View current database connection status and basic information."
-      },
-      "cleanup": {
-        "title": "Log Cleanup",
-        "description": "Clean up historical log data to free up database storage. Note: Statistics data will be retained, but log details will be permanently deleted."
-      },
-      "export": {
-        "title": "Data Export",
-        "description": "Export complete database backup file (.dump format) for data migration or recovery."
-      },
-      "import": {
-        "title": "Data Import",
-        "description": "Restore database from backup file. Supports PostgreSQL custom format (.dump) backup files."
-      }
-    }
-  },
-  "errors": {
-    "saveSuccess": "Save succeeded",
-    "saveFailed": "Save failed",
-    "saveFailed_error": "Failed to save settings",
-    "addSuccess": "Add succeeded",
-    "addFailed": "Failed to add provider",
-    "editSuccess": "Update succeeded",
-    "editFailed": "Failed to update provider",
-    "deleteSuccess": "Delete succeeded",
-    "deleteFailed": "Failed to delete provider",
-    "syncSuccess": "Sync succeeded",
-    "syncFailed": "Sync failed",
-    "testFailed": "Test failed",
-    "testFailedRetry": "Test failed, please retry",
-    "loadFailed": "Failed to load notification settings",
-    "unknownError": "An exception occurred during the operation"
-  },
-  "logs": {
-    "description": "Dynamically adjust system log level to control logging verbosity in real-time.",
-    "subtitle": "Log Level Control",
-    "subtitleDesc": "Changes take effect immediately without restart. Useful for troubleshooting in production.",
-    "section": {
-      "title": "Log Level Control",
-      "description": "Changes take effect immediately without service restart."
-    },
-    "levels": {
-      "fatal": {
-        "label": "Fatal",
-        "description": "Fatal errors only"
-      },
-      "error": {
-        "label": "Error",
-        "description": "Error messages"
-      },
-      "warn": {
-        "label": "Warn",
-        "description": "Warnings + Errors"
-      },
-      "info": {
-        "label": "Info",
-        "description": "Key business events + Warnings + Errors (Recommended for Production)"
-      },
-      "debug": {
-        "label": "Debug",
-        "description": "Debug info + All levels (Recommended for Development)"
-      },
-      "trace": {
-        "label": "Trace",
-        "description": "Extremely detailed tracing + All levels"
-      }
-    },
-    "form": {
-      "currentLevel": "Current Log Level",
-      "selectLevel": "Select Log Level",
-      "save": "Save Settings",
-      "saving": "Saving...",
-      "success": "Log level set to: {level}",
-      "failed": "Failed to set",
-      "failedError": "Failed to set log level",
-      "fetchFailed": "Failed to fetch log level",
-      "effectiveImmediately": "Log level changes take effect immediately without service restart.",
-      "levelGuideTitle": "Log Level Guide",
-      "levelGuideFatal": "Fatal/Error: Only errors shown, minimal logging, suitable for high-load production",
-      "levelGuideWarn": "Warn: Includes warnings (rate limiting, circuit breaker opening, etc.) + Errors",
-      "levelGuideInfo": "Info (Recommended for Production): Shows key business events (provider selection, Session reuse, price sync) + Warnings + Errors",
-      "levelGuideDebug": "Debug (Recommended for Development): Includes detailed debug info, suitable for troubleshooting",
-      "levelGuideTrace": "Trace: Extremely detailed trace information, includes all details",
-      "changeNotice": "Current level is {current}, will switch to {selected} after saving"
-    },
-    "title": "Log Management"
-  },
-  "nav": {
-    "apiDocs": "API Docs",
-    "clientVersions": "Updates",
-    "config": "Config",
-    "data": "Data",
-    "errorRules": "Errors",
-    "feedback": "Feedback",
-    "docs": "Documentation",
-    "logs": "Logs",
-    "notifications": "Notifications",
-    "prices": "Pricing",
-    "providers": "Providers",
-    "sensitiveWords": "Filters",
-    "requestFilters": "Requests"
-  },
-  "notifications": {
-    "title": "Push Notifications",
-    "description": "Configure Webhook push notifications",
-  "global": {
-    "title": "Notification Master Switch",
-    "description": "Enable or disable all push notification features",
-    "enable": "Enable Push Notifications",
-    "legacyModeTitle": "Legacy Mode",
-    "legacyModeDescription": "You are using legacy single-URL notifications. Create a push target to switch to multi-target mode."
-  },
-  "targets": {
-    "title": "Push Targets",
-    "description": "Manage push targets. Supports WeCom, Feishu, DingTalk, Telegram and custom Webhook.",
-    "add": "Add Target",
-    "update": "Save Target",
-    "edit": "Edit",
-    "delete": "Delete",
-    "deleteConfirmTitle": "Delete Push Target",
-    "deleteConfirm": "Are you sure you want to delete this target? Related bindings will also be removed.",
-    "enable": "Enable Target",
-    "statusEnabled": "Enabled",
-    "statusDisabled": "Disabled",
-    "lastTestAt": "Last Test",
-    "lastTestNever": "Never tested",
-    "lastTestSuccess": "Test OK",
-    "lastTestFailed": "Test Failed",
-    "test": "Test",
-    "testSelectType": "Select test type",
-    "emptyHint": "No push targets yet. Click \"Add Target\" to create one.",
-    "created": "Target created",
-    "updated": "Target updated",
-    "deleted": "Target deleted",
-    "bindingsSaved": "Bindings saved"
-  },
-  "targetDialog": {
-    "createTitle": "Add Push Target",
-    "editTitle": "Edit Push Target",
-    "name": "Target Name",
-    "namePlaceholder": "e.g. Ops Group",
-    "type": "Platform Type",
-    "selectType": "Select platform type",
-    "enable": "Enable",
-    "webhookUrl": "Webhook URL",
-    "webhookUrlPlaceholder": "https://example.com/webhook",
-    "telegramBotToken": "Telegram Bot Token",
-    "telegramBotTokenPlaceholder": "e.g. 123456:ABCDEF...",
-    "telegramChatId": "Telegram Chat ID",
-    "telegramChatIdPlaceholder": "e.g. -1001234567890",
-    "dingtalkSecret": "DingTalk Secret",
-    "dingtalkSecretPlaceholder": "Optional, used for signing",
-    "customHeaders": "Custom Headers (JSON)",
-    "customHeadersPlaceholder": "{\"X-Token\":\"...\"}",
-    "errors": {
-      "headersInvalidJson": "Headers must be valid JSON",
-      "headersMustBeObject": "Headers must be a JSON object",
-      "headersValueMustBeString": "Header values must be strings"
-    },
-    "types": {
-      "wechat": "WeCom",
-      "feishu": "Feishu",
-      "dingtalk": "DingTalk",
-      "telegram": "Telegram",
-      "custom": "Custom Webhook"
-    },
-    "proxy": {
-      "title": "Proxy",
-      "toggle": "Toggle proxy settings",
-      "url": "Proxy URL",
-      "urlPlaceholder": "http://127.0.0.1:7890",
-      "fallbackToDirect": "Fallback to direct on proxy failure"
-    }
-  },
-  "bindings": {
-    "title": "Bindings",
-    "noTargets": "No push targets available.",
-    "bindTarget": "Bind target",
-    "enable": "Enable",
-    "enableType": "Enable this notification",
-    "advanced": "Advanced",
-    "scheduleCron": "Cron",
-    "scheduleCronPlaceholder": "e.g. 0 9 * * *",
-    "scheduleTimezone": "Timezone",
-    "templateOverride": "Template Override",
-    "editTemplateOverride": "Edit Override",
-    "templateOverrideTitle": "Edit Template Override",
-    "boundCount": "Bound: {count}",
-    "enabledCount": "Enabled: {count}"
-  },
-  "templateEditor": {
-    "title": "Template (JSON)",
-    "placeholder": "Enter JSON template...",
-    "jsonInvalid": "Invalid JSON",
-    "placeholders": "Placeholders",
-    "insert": "Insert"
-  },
-  "circuitBreaker": {
-    "title": "Circuit Breaker Alert",
-    "description": "Send alert immediately when provider is fully circuit broken",
-      "enable": "Enable Circuit Breaker Alert",
-      "webhook": "Webhook URL",
-      "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...",
-      "test": "Test Connection"
-    },
-    "dailyLeaderboard": {
-      "title": "Daily User Consumption Leaderboard",
-      "description": "Send daily scheduled user consumption Top N leaderboard",
-      "enable": "Enable Daily Leaderboard",
-      "webhook": "Webhook URL",
-      "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...",
-      "time": "Send Time",
-      "timePlaceholder": "09:00",
-      "timeError": "Time format error, should be HH:mm",
-      "topN": "Show Top N",
-      "test": "Test Connection"
-    },
-    "costAlert": {
-      "title": "Cost Alert",
-      "description": "Trigger alert when user/provider consumption exceeds quota threshold",
-      "enable": "Enable Cost Alert",
-      "webhook": "Webhook URL",
-      "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...",
-      "webhookTypeWeCom": "WeCom",
-      "webhookTypeFeishu": "Feishu",
-      "webhookTypeUnknown": "Unknown platform. Please use WeCom or Feishu webhook URL",
-      "threshold": "Alert Threshold",
-      "thresholdLabel": "Alert Threshold: {percent}%",
-      "thresholdHelp": "Alert when consumption reaches {percent}% of quota",
-      "interval": "Check Interval (minutes)",
-      "test": "Test Connection"
-    },
-    "form": {
-      "save": "Save Settings",
-      "saving": "Saving...",
-      "loading": "Loading...",
-      "success": "Notification settings saved and tasks rescheduled",
-      "saveFailed": "Save failed",
-      "saveError": "Failed to save settings",
-      "loadError": "Failed to load notification settings",
-      "webhookRequired": "Please fill in Webhook URL first",
-      "testSuccess": "Test message sent",
-      "testFailed": "Test failed",
-      "testFailedRetry": "Test failed, please retry",
-      "testError": "Test connection failed",
-      "testNoResult": "Test succeeded but no result returned"
-    }
-  },
-  "prices": {
-    "title": "Pricing",
-    "description": "Manage platform basic configuration and model pricing",
-    "section": {
-      "title": "Model Pricing",
-      "description": "Manage AI model pricing configuration"
-    },
-    "searchPlaceholder": "Search model name...",
-    "filters": {
-      "all": "All",
-      "local": "Local",
-      "anthropic": "Anthropic",
-      "openai": "OpenAI",
-      "vertex": "Vertex"
-    },
-    "badges": {
-      "local": "Local"
-    },
-    "capabilities": {
-      "assistantPrefill": "Assistant prefill",
-      "computerUse": "Computer use",
-      "functionCalling": "Function calling",
-      "pdfInput": "PDF input",
-      "promptCaching": "Prompt caching",
-      "reasoning": "Reasoning",
-      "responseSchema": "Response schema",
-      "toolChoice": "Tool choice",
-      "vision": "Vision",
-      "statusSupported": "Supported",
-      "statusUnsupported": "Not supported",
-      "tooltip": "{label}: {status}"
-    },
-    "sync": {
-      "button": "Sync Cloud Price Table",
-      "syncing": "Syncing...",
-      "checking": "Checking conflicts...",
-      "successWithChanges": "Price table updated: {added} added, {updated} updated, {unchanged} unchanged",
-      "successNoChanges": "Price table is up to date, no updates needed",
-      "failed": "Sync failed",
-      "failedError": "Sync failed: {error}",
-      "failedNoResult": "Price table updated but no result returned",
-      "noModels": "No model prices found",
-      "partialFailure": "Partial update succeeded, but {failed} models failed",
-      "failedModels": "Failed models: {models}",
-      "skippedConflicts": "Skipped {count} manual models"
-    },
-    "conflict": {
-      "title": "Select Items to Overwrite",
-      "description": "The following models have manual prices. Check the ones to overwrite with LiteLLM prices, unchecked ones will be kept unchanged",
-      "searchPlaceholder": "Search models...",
-      "table": {
-        "modelName": "Model",
-        "manualPrice": "Manual Price",
-        "litellmPrice": "LiteLLM Price",
-        "action": "Action"
-      },
-      "viewDiff": "View Diff",
-      "diffTitle": "Price Difference",
-      "diff": {
-        "field": "Field",
-        "manual": "Manual",
-        "litellm": "LiteLLM",
-        "inputPrice": "Input Price",
-        "outputPrice": "Output Price",
-        "imagePrice": "Image Price",
-        "provider": "Provider",
-        "mode": "Type"
-      },
-      "pagination": {
-        "showing": "Showing {from}-{to} of {total}"
-      },
-      "selectedCount": "Selected {count}/{total} models",
-      "noMatch": "No matching models found",
-      "noConflicts": "No conflicts",
-      "applyOverwrite": "Apply Overwrite",
-      "applying": "Applying..."
-    },
-    "table": {
-      "modelName": "Model Name",
-      "provider": "Provider",
-      "capabilities": "Capabilities",
-      "price": "Price",
-      "inputPrice": "Input Price ($/M)",
-      "outputPrice": "Output Price ($/M)",
-      "priceInput": "In",
-      "priceOutput": "Out",
-      "pricePerRequest": "Req",
-      "cacheReadPrice": "Cache Read ($/M)",
-      "cacheCreationPrice": "Cache Create ($/M)",
-      "cache5m": "5m",
-      "cache1h": "1h+",
-      "copyModelId": "Copy model ID",
-      "updatedAt": "Updated At",
-      "actions": "Actions",
-      "typeChat": "Chat",
-      "typeImage": "Image",
-      "typeCompletion": "Completion",
-      "typeUnknown": "Unknown",
-      "loading": "Loading...",
-      "noMatch": "No matching models found",
-      "noDataTitle": "No price data available",
-      "noDataHint": "System has built-in price table. Use buttons above to sync or update."
-    },
-    "pagination": {
-      "showing": "Showing {from}-{to} of {total}",
-      "previous": "Previous",
-      "next": "Next",
-      "perPageLabel": "Per page",
-      "perPage": "{size} per page"
-    },
-    "stats": {
-      "totalModels": "{count} models total",
-      "searchResults": "{count} search results",
-      "lastUpdated": "Last updated: {time}"
-    },
-    "dialog": {
-      "title": "Update Model Price Table",
-      "description": "Select and upload JSON or TOML file containing model pricing data",
-      "selectFile": "Click to select JSON/TOML file or drag and drop here",
-      "fileSizeLimit": "File size cannot exceed 10MB",
-      "fileSizeLimitSmall": "File size not exceeding 10MB",
-      "invalidFileType": "Please select a JSON or TOML file",
-      "fileTooLarge": "File size exceeds 10MB limit",
-      "upload": "Upload and Update",
-      "uploading": "Uploading...",
-      "updatePriceTable": "Update Price Table",
-      "updating": "Updating...",
-      "selectJson": "Select File",
-      "updateSuccess": "Price table updated successfully, {count} models updated",
-      "updateFailed": "Update failed",
-      "systemHasBuiltIn": "System has built-in price table",
-      "manualDownload": "You can also manually download",
-      "latestPriceTable": "cloud price table",
-      "andUploadViaButton": ", and upload via button above",
-      "cloudModelCountLoading": "Loading cloud model count...",
-      "cloudModelCountFailed": "Failed to load cloud model count",
-      "supportedModels": "Currently supports {count} models",
-      "results": {
-        "title": "Update Results",
-        "total": "Total: {total} models",
-        "success": "Success: {success}",
-        "failed": "Failed: {failed}",
-        "skipped": "Skipped: {skipped}",
-        "more": " (+{count})",
-        "details": "Details",
-        "viewDetails": "View detailed logs"
-      }
-    },
-    "addModel": "Add Model",
-    "editModel": "Edit Model",
-    "deleteModel": "Delete Model",
-    "addModelDescription": "Manually add a new model price configuration",
-    "editModelDescription": "Edit the model price configuration",
-    "deleteConfirm": "Are you sure you want to delete model {name}? This action cannot be undone.",
-    "form": {
-      "modelName": "Model ID",
-      "modelNamePlaceholder": "e.g., gpt-5.2-codex",
-      "modelNameRequired": "Model ID is required",
-      "displayName": "Display Name (Optional)",
-      "displayNamePlaceholder": "e.g., GPT-5.2 Codex",
-      "type": "Type",
-      "provider": "Provider",
-      "providerPlaceholder": "e.g., openai",
-      "requestPrice": "Per-call Price ($/request)",
-      "inputPrice": "Input Price ($/M tokens)",
-      "outputPrice": "Output Price ($/M tokens)",
-      "outputPriceImage": "Output Price ($/image)",
-      "cacheReadPrice": "Cache Read Price ($/M tokens)",
-      "cacheCreationPrice5m": "Cache Creation Price (5m, $/M tokens)",
-      "cacheCreationPrice1h": "Cache Creation Price (1h+, $/M tokens)"
-    },
-    "drawer": {
-      "prefillLabel": "Search existing models to prefill",
-      "prefillEmpty": "No matching models found",
-      "prefillFailed": "Search failed",
-      "promptCachingHint": "Enable if the model supports prompt caching",
-      "cachePricingTitle": "Cache Pricing"
-    },
-    "actions": {
-      "edit": "Edit",
-      "more": "More actions",
-      "delete": "Delete"
-    },
-    "toast": {
-      "createSuccess": "Model added",
-      "updateSuccess": "Model updated",
-      "deleteSuccess": "Model deleted",
-      "saveFailed": "Failed to save",
-      "deleteFailed": "Failed to delete"
-    }
-  },
-  "providers": {
-    "add": "Add Provider",
-    "addFailed": "Failed to add provider",
-    "addProvider": "Add Provider",
-    "addSuccess": "Provider added successfully",
-    "autoSort": {
-      "button": "Auto Sort Priority",
-      "dialogTitle": "Auto Sort Provider Priority",
-      "dialogDescription": "Automatically assign priority based on cost multiplier (lower cost = higher priority)",
-      "changeCount": "{count} providers will be updated",
-      "noChanges": "No changes needed (already sorted)",
-      "costMultiplierHeader": "Cost Multiplier",
-      "priorityHeader": "Priority",
-      "providersHeader": "Providers",
-      "changesTitle": "Change Details",
-      "providerHeader": "Provider",
-      "priorityChangeHeader": "Priority Change",
-      "confirm": "Apply Changes",
-      "success": "Updated priority for {count} providers",
-      "error": "Failed to update priorities"
-    },
-    "types": {
-      "claude": {
-        "label": "Claude",
-        "description": "Anthropic Official API"
-      },
-      "claudeAuth": {
-        "label": "Claude Auth",
-        "description": "Claude Relay Service"
-      },
-      "codex": {
-        "label": "Codex",
-        "description": "Codex CLI API"
-      },
-      "gemini": {
-        "label": "Gemini",
-        "description": "Google Gemini API"
-      },
-      "geminiCli": {
-        "label": "Gemini CLI",
-        "description": "Gemini CLI API"
-      },
-      "openaiCompatible": {
-        "label": "OpenAI Compatible",
-        "description": "OpenAI Compatible API"
-      }
-    },
-    "list": {
-      "priority": "Priority",
-      "weight": "Weight",
-      "costMultiplier": "Cost Multiplier",
-      "todayUsageLabel": "Today's Usage",
-      "todayUsageCount": "{count} times",
-      "circuitBroken": "Circuit Broken",
-      "officialWebsite": "Official",
-      "viewFullKey": "View Complete API Key",
-      "viewFullKeyDesc": "Please keep it safe and don't share it with others",
-      "keyLoading": "Loading...",
-      "confirmDeleteTitle": "Confirm Delete Provider?",
-      "confirmDeleteMessage": "Are you sure you want to delete provider \"{name}\"? This action cannot be undone.",
-      "deleteButton": "Delete",
-      "cancelButton": "Cancel",
-      "deleteSuccess": "Deleted successfully",
-      "deleteSuccessDesc": "Provider \"{name}\" has been deleted",
-      "deleteFailed": "Delete failed",
-      "deleteError": "An error occurred during operation",
-      "unknownError": "Unknown error",
-      "getKeyFailed": "Failed to get key",
-      "keyCopied": "Key copied to clipboard",
-      "copyFailed": "Copy failed",
-      "clipboardUnavailable": "Clipboard access is blocked in this environment. Select and copy the key manually.",
-      "resetCircuitSuccess": "Circuit breaker reset",
-      "resetCircuitSuccessDesc": "Provider \"{name}\" circuit breaker status cleared",
-      "resetCircuitFailed": "Failed to reset circuit breaker",
-      "resetUsageTitle": "Reset total usage",
-      "resetUsageSuccess": "Total usage reset",
-      "resetUsageSuccessDesc": "Provider \"{name}\" total usage has been reset",
-      "resetUsageFailed": "Failed to reset total usage",
-      "toggleSuccess": "Provider {status}",
-      "toggleSuccessDesc": "Provider \"{name}\" status updated",
-      "toggleFailed": "Toggle failed",
-      "statusEnabled": "enabled",
-      "statusDisabled": "disabled"
-    },
-    "inlineEdit": {
-      "save": "Save",
-      "cancel": "Cancel",
-      "saveSuccess": "Saved successfully",
-      "saveFailed": "Save failed",
-      "priorityLabel": "Priority",
-      "weightLabel": "Weight",
-      "costMultiplierLabel": "Cost Multiplier",
-      "priorityInvalid": "Please enter an integer >= 0",
-      "weightInvalid": "Please enter an integer between 1 and 100",
-      "costMultiplierInvalid": "Please enter a non-negative number"
-    },
-    "schedulingDialog": {
-      "title": "Provider Scheduling Rules",
-      "description": "Understand how the system intelligently selects upstream providers for high availability and cost optimization",
-      "triggerButton": "Rules",
-      "step": "Step",
-      "before": "Before:",
-      "after": "After:",
-      "decision": "Decision:"
-    },
-    "circuitBroken": "Circuit Broken",
-    "clone": "Clone Provider",
-    "cloneFailed": "Copy failed",
-    "confirmDelete": "Are you sure you want to delete this provider?",
-    "confirmDeleteDesc": "Are you sure you want to delete provider \"{name}\"? This action cannot be undone.",
-    "confirmDeleteProvider": "Confirm Delete Provider?",
-    "confirmDeleteProviderDesc": "Are you sure you want to delete provider \"{name}\"? This action is irreversible.",
-    "createProvider": "Add Provider",
-    "delete": "Delete Provider",
-    "deleteFailed": "Failed to delete provider",
-    "deleteSuccess": "Deleted successfully",
-    "description": "Configure API service providers and maintain availability status.",
-    "disabledStatus": "disabled",
-    "displayCount": "Showing {filtered} / {total} providers",
-    "edit": "Edit Provider",
-    "editFailed": "Failed to update provider",
-    "editProvider": "Edit Provider",
-    "enabledStatus": "enabled",
-    "form": {
-      "apiTest": {
-        "fillUrlFirst": "Please fill in provider URL first",
-        "invalidUrl": "Provider URL is invalid (http/https only)",
-        "fillKeyFirst": "Please fill in API key first",
-        "testFailed": "Test failed",
-        "testFailedRetry": "Test failed, please retry",
-        "noResult": "Test succeeded but no result returned",
-        "testSuccess": "Model test succeeded",
-        "testApi": "Provider Model Test",
-        "testing": "Testing...",
-        "apiFormat": "Provider type",
-        "selectApiFormat": "Select provider type to test",
-        "apiFormatDesc": "Defaults to the routing configuration unless manually changed",
-        "formatAnthropicMessages": "Claude (Anthropic Messages API)",
-        "formatOpenAIChat": "OpenAI Compatible",
-        "formatOpenAIResponses": "Codex (Response API)",
-        "testModel": "Test model",
-        "testModelDesc": "Leave empty to use the default model or type one manually",
-        "requestConfig": "Request Configuration",
-        "presetConfig": "Preset",
-        "customConfig": "Custom",
-        "selectPreset": "Select preset template",
-        "presetDesc": "Preset templates contain authentic CLI request patterns for relay service verification",
-        "customPayloadPlaceholder": "{\"model\": \"...\", \"messages\": [...]}",
-        "customPayloadDesc": "Enter custom JSON payload to override default request body",
-        "successContains": "Success Keyword",
-        "successContainsPlaceholder": "pong",
-        "successContainsDesc": "Response must contain this keyword to be considered successful",
-        "model": "Model",
-        "responseModel": "Response model",
-        "responseTime": "Response time",
-        "usage": "Token usage",
-        "response": "Response preview",
-        "error": "Error message",
-        "unknown": "Unknown",
-        "viewDetails": "View Details",
-        "copySuccess": "Copied to clipboard",
-        "copyFailed": "Failed to copy",
-        "copyResult": "Copy Result",
-        "close": "Close",
-        "success": "Success",
-        "failed": "Failed",
-        "streamInfo": "Stream response info",
-        "chunksReceived": "Chunks received",
-        "streamFormat": "Stream format",
-        "streamResponse": "Stream response",
-        "chunksCount": "Received {count} chunks ({format})",
-        "truncatedPreview": "Showing first {length} characters, copy to see full content",
-        "truncatedBrief": "Showing first {length} characters, click \"View Details\" for more",
-        "timeout": {
-          "label": "Timeout (seconds)",
-          "desc": "Max wait time for test request (5-120 sec)",
-          "geminiHint": ", Gemini Thinking models recommend 60+ sec"
-        },
-        "geminiAuthFallback": {
-          "warning": "Header auth failed, using URL parameter auth",
-          "desc": "Actual proxy forwarding only uses header auth, may cause request failures"
-        },
-        "copyFormat": {
-          "testResult": "Test result",
-          "message": "Message",
-          "errorDetails": "Error details"
-        },
-        "disclaimer": {
-          "title": "Notice",
-          "resultReference": "[IMPORTANT] Results may vary by provider and are for reference only",
-          "realRequest": "This test sends a real request to the provider and may consume a small quota",
-          "confirmConfig": "Please verify provider URL, API key, and model configuration"
-        },
-        "resultCard": {
-          "status": {
-            "green": "Available",
-            "yellow": "Degraded",
-            "red": "Unavailable"
-          },
-          "dialogTitle": "Provider Test Details",
-          "validation": {
-            "title": "Three-tier Validation Details",
-            "http": {
-              "title": "Tier 1: HTTP Status",
-              "statusCode": "Status Code",
-              "passed": "2xx/3xx Success",
-              "failed": "4xx/5xx Failed"
-            },
-            "latency": {
-              "title": "Tier 2: Latency Threshold",
-              "actual": "Actual Latency",
-              "passed": "Within threshold",
-              "failed": "Exceeded threshold"
-            },
-            "content": {
-              "title": "Tier 3: Content Validation",
-              "target": "Target",
-              "passed": "Contains target string",
-              "failed": "Target not found"
-            },
-            "passed": "Passed",
-            "failed": "Failed",
-            "timeout": "Timeout"
-          },
-          "labels": {
-            "http": "HTTP",
-            "latency": "Latency",
-            "content": "Content",
-            "model": "Model",
-            "firstByte": "First Byte",
-            "totalLatency": "Total Latency",
-            "error": "Error",
-            "responsePreview": "Response Preview"
-          },
-          "timing": {
-            "title": "Timing Info",
-            "totalLatency": "Total Latency",
-            "firstByte": "First Byte",
-            "testedAt": "Tested At"
-          },
-          "tokenUsage": {
-            "title": "Token Usage",
-            "input": "Input",
-            "output": "Output",
-            "cacheCreation": "Cache Creation",
-            "cacheRead": "Cache Read"
-          },
-          "streamInfo": {
-            "title": "Stream Response Info",
-            "isStreaming": "Streaming",
-            "chunksCount": "Chunks Count",
-            "yes": "Yes",
-            "no": "No"
-          },
-          "rawResponse": {
-            "title": "Raw Response Body",
-            "hint": "This shows the raw response content. You can check if the keyword exists in the response here."
-          },
-          "errorDetails": {
-            "title": "Error Details",
-            "type": "Error Type"
-          },
-          "copyText": {
-            "status": "Status",
-            "message": "Message",
-            "latency": "Latency",
-            "httpStatus": "HTTP Status",
-            "model": "Model",
-            "usage": "Usage",
-            "inputOutput": "Input {input} / Output {output} tokens",
-            "response": "Response",
-            "error": "Error",
-            "testedAt": "Tested At",
-            "validationDetails": "Validation Details",
-            "httpCheck": "HTTP Check",
-            "latencyCheck": "Latency Check",
-            "contentCheck": "Content Check"
-          },
-          "judgment": "Judgment"
-        }
-      },
-      "proxyTest": {
-        "fillUrlFirst": "Please fill in provider URL first",
-        "testFailed": "Test failed",
-        "testFailedRetry": "Test failed, please retry",
-        "noResult": "Test succeeded but no result returned",
-        "connectionSuccess": "Connection successful",
-        "connectionFailed": "Connection failed",
-        "viaProxy": "(via proxy)",
-        "viaDirect": "(direct)",
-        "responseTime": "Response time:",
-        "statusCode": "Status code:",
-        "connectionMethod": "Connection method:",
-        "proxy": "Proxy",
-        "direct": "Direct",
-        "errorType": "Error type:",
-        "testing": "Testing...",
-        "testConnection": "Test Connection",
-        "timeoutError": "Connection timeout (5s). Please check:\n1. Is proxy server accessible\n2. Are proxy address and port correct\n3. Are proxy credentials correct",
-        "proxyError": "Proxy error:",
-        "networkError": "Network error:"
-      },
-      "urlPreview": {
-        "title": "URL Concatenation Preview",
-        "invalidUrl": "Invalid URL format",
-        "invalidUrlDesc": "Please enter a valid HTTP/HTTPS address",
-        "duplicatePath": "Duplicate path detected",
-        "copy": "Copy",
-        "copySuccess": "Copied {name} to clipboard",
-        "copyFailed": "Copy failed"
-      },
-      "modelSelect": {
-        "allowAllModels": "Allow all {type} models",
-        "selectedCount": "Selected {count} models",
-        "searchPlaceholder": "Search model name...",
-        "loading": "Loading...",
-        "notFound": "Model not found",
-        "selectAll": "Select All ({count})",
-        "clear": "Clear",
-        "manualAdd": "Manually Add Model",
-        "manualPlaceholder": "Enter model name (e.g. gpt-5-turbo)",
-        "manualDesc": "Support adding any model name (not limited to price table)",
-        "claude": "Claude",
-        "openai": "OpenAI",
-        "gemini": "Gemini",
-        "sourceUpstream": "Upstream",
-        "sourceUpstreamDesc": "Model list from upstream provider API",
-        "sourceFallback": "Local",
-        "sourceFallbackDesc": "Using local price list (upstream unavailable or unsupported)",
-        "refresh": "Refresh model list"
-      },
-      "modelRedirect": {
-        "currentRules": "Current Rules ({count})",
-        "addNewRule": "Add New Rule",
-        "sourceModel": "User Requested Model",
-        "targetModel": "Actual Forwarded Model",
-        "sourcePlaceholder": "e.g. claude-sonnet-4-5-20250929",
-        "targetPlaceholder": "e.g. glm-4.6",
-        "add": "Add",
-        "sourceEmpty": "Source model name cannot be empty",
-        "targetEmpty": "Target model name cannot be empty",
-        "alreadyExists": "Model \"{model}\" already has a redirect rule",
-        "description": "Redirect Claude Code client requested models (e.g. claude-sonnet-4.5) to upstream provider supported models (e.g. glm-4.6, gemini-pro). For cost optimization or third-party AI integration.",
-        "emptyState": "No redirect rules yet. After adding rules, the system will automatically rewrite model names in requests."
-      },
-      "addRedirect": "Add Redirect",
-      "allowAllModels": "✓ Allow All Models (Recommended)",
-      "apiAddress": "API Address",
-      "apiAddressPlaceholder": "e.g. https://open.bigmodel.cn/api/anthropic",
-      "apiAddressRequired": "API Address *",
-      "apiKey": "API Key",
-      "apiKeyCurrent": "Current key:",
-      "apiKeyLeaveEmpty": "(Leave empty to keep unchanged)",
-      "apiKeyLeaveEmptyDesc": "Leave empty to keep existing key",
-      "apiKeyOptional": "Leave empty to keep existing key",
-      "apiKeyPlaceholder": "Enter API key",
-      "apiKeyRequired": "API Key *",
-      "baseUrl": "Base URL",
-      "baseUrlPlaceholder": "e.g. https://open.bigmodel.cn/api/anthropic",
-      "baseUrlRequired": "Please fill in provider URL first",
-      "circuitBreakerConfig": "Circuit Breaker Configuration",
-      "circuitBreakerConfigSummary": "{failureThreshold} failures / {openDuration} min circuit break / {successThreshold} successes to recover / {maxRetryAttempts} attempts per provider",
-      "circuitBreakerDesc": "Auto circuit break on consecutive failures to avoid overall service quality impact",
-      "clearSearch": "Clear search",
-      "codexInstructions": "Codex Instructions Policy",
-      "codexInstructionsAuto": "Auto (Recommended)",
-      "codexInstructionsDesc": "(determines scheduling policy)",
-      "codexInstructionsForce": "Force Official",
-      "codexInstructionsKeep": "Keep Original",
-      "codexStrategyAutoDesc": "Pass through client instructions, auto retry with official prompt on 400 error",
-      "codexStrategyAutoLabel": "Auto (Recommended)",
-      "codexStrategyConfig": "Codex Instructions Strategy",
-      "codexStrategyConfigAuto": "Auto (Recommended)",
-      "codexStrategyConfigForce": "Force Official",
-      "codexStrategyConfigKeep": "Keep Original",
-      "codexStrategyDesc": "Control how to handle Codex request instructions field, affects upstream gateway compatibility",
-      "codexStrategyForceDesc": "Always use official Codex CLI instructions (~4000+ chars)",
-      "codexStrategyForceLabel": "Force Official",
-      "codexStrategyHint": "Hint: Some strict Codex gateways (e.g. 88code, foxcode) require official instructions. Choose \"Auto\" or \"Force Official\" strategy",
-      "mcpPassthroughConfig": "MCP Passthrough Configuration",
-      "mcpPassthroughConfigMinimax": "Minimax",
-      "mcpPassthroughConfigGlm": "GLM",
-      "mcpPassthroughConfigCustom": "Custom (Reserved)",
-      "mcpPassthroughConfigNone": "Disabled",
-      "mcpPassthroughDesc": "When enabled, pass through MCP tool calls to specified AI provider (e.g. minimax for image recognition, web search)",
-      "mcpPassthroughSelect": "Passthrough Type",
-      "mcpPassthroughNoneLabel": "Disabled",
-      "mcpPassthroughNoneDesc": "Do not enable MCP passthrough (default)",
-      "mcpPassthroughMinimaxLabel": "Minimax",
-      "mcpPassthroughMinimaxDesc": "Pass through to minimax MCP service (supports image recognition, web search, etc.)",
-      "mcpPassthroughGlmLabel": "GLM",
-      "mcpPassthroughGlmDesc": "Pass through to GLM MCP service (supports image analysis, video analysis, etc.)",
-      "mcpPassthroughCustomLabel": "Custom",
-      "mcpPassthroughCustomDesc": "Pass through to custom MCP service (reserved, not implemented yet)",
-      "mcpPassthroughHint": "Hint: MCP passthrough allows Claude Code client to use tool capabilities provided by third-party AI providers (e.g. image recognition, web search)",
-      "codexStrategyKeepDesc": "Always pass through client instructions, no auto retry (for lenient gateways)",
-      "codexStrategyKeepLabel": "Keep Original",
-      "codexStrategySelect": "Strategy Selection",
-      "collapseAll": "Collapse All Advanced Configuration",
-      "confirmAdd": "Confirm Add",
-      "confirmAddPending": "Adding...",
-      "confirmUpdate": "Confirm Update",
-      "confirmUpdatePending": "Updating...",
-      "costMultiplier": "Cost Multiplier",
-      "costMultiplierDesc": "Cost calculation multiplier. Official=1.0, 20% cheaper=0.8, 20% more expensive=1.2 (up to 4 decimal places)",
-      "costMultiplierLabel": "Cost Multiplier",
-      "costMultiplierPlaceholder": "1.0",
-      "deleteButton": "Delete",
-      "enabled": "Enabled",
-      "expandAll": "Expand All Advanced Configuration",
-      "failureThreshold": "Failure Threshold (times)",
-      "failureThresholdDesc": "How many consecutive failures trigger circuit break",
-      "failureThresholdPlaceholder": "5",
-      "filterAllProviders": "All Providers",
-      "filterByType": "Filter by Provider Type",
-      "filterProvider": "Filter by Provider Type",
-      "group": "Group",
-      "groupPlaceholder": "e.g. premium, economy",
-      "joinClaudePool": "Join Claude Scheduling Pool",
-      "joinClaudePoolDesc": "When enabled, this provider will participate in load balancing with Claude type providers",
-      "joinClaudePoolHelp": "Only available when model redirect config contains mappings to claude-* models. When enabled, this provider will also participate in scheduling when users request claude-* models.",
-      "leaveEmpty": "Leave empty for unlimited",
-      "limit0Means": "0 means unlimited",
-      "limit5hLabel": "5-Hour Spending Limit (USD)",
-      "limitAmount5h": "5-Hour Spending Limit (USD)",
-      "limitAmount5hDesc": "e.g. Provider B has $10 limit, $9.8 consumed",
-      "limitAmountMonthly": "Monthly Spending Limit (USD)",
-      "limitAmountWeekly": "Weekly Spending Limit (USD)",
-      "limitConcurrent": "Concurrent Session Limit",
-      "limitConcurrentDesc": "e.g. Provider C has limit of 2, currently 2 active sessions",
-      "limitConcurrentLabel": "Concurrent Session Limit",
-      "limitMonthlyLabel": "Monthly Spending Limit (USD)",
-      "limitPlaceholder0": "0 means unlimited",
-      "limitPlaceholderUnlimited": "Leave empty for unlimited",
-      "limitWeeklyLabel": "Weekly Spending Limit (USD)",
-      "modelRedirects": "Model Redirects",
-      "modelRedirectsAddNew": "Add New Rule",
-      "modelRedirectsCurrentRules": "Current Rules ({count})",
-      "modelRedirectsDesc": "Redirect Claude Code client model requests (e.g. claude-sonnet-4.5) to upstream provider supported models (e.g. glm-4.6, gemini-pro). For cost optimization or third-party AI integration.",
-      "modelRedirectsEmpty": "No redirect rules yet. System will auto-rewrite model names after adding rules.",
-      "modelRedirectsExists": "Model \"{model}\" already has a redirect rule",
-      "modelRedirectsLabel": "Model Redirects Configuration",
-      "modelRedirectsOptional": "(Optional)",
-      "modelRedirectsSourceModel": "User Requested Model",
-      "modelRedirectsSourcePlaceholder": "e.g. claude-sonnet-4-5-20250929",
-      "modelRedirectsSourceRequired": "Source model name cannot be empty",
-      "modelRedirectsTargetModel": "Actual Forwarded Model",
-      "modelRedirectsTargetPlaceholder": "e.g. glm-4.6",
-      "modelRedirectsTargetRequired": "Target model name cannot be empty",
-      "modelWhitelist": "Model Whitelist",
-      "modelWhitelistAllowAll": "Allow all {type} models",
-      "modelWhitelistAllowAllClause": "Allow all Claude models",
-      "modelWhitelistAllowAllOpenAI": "Allow all OpenAI models",
-      "modelWhitelistClear": "Clear",
-      "modelWhitelistDesc": "Limit models this provider can handle. By default, provider can handle all models of its type.",
-      "modelWhitelistLabel": "Allowed Models",
-      "modelWhitelistLoading": "Loading...",
-      "modelWhitelistManualAdd": "Manually Add Model",
-      "modelWhitelistManualDesc": "Support adding any model name (not limited to price table)",
-      "modelWhitelistManualPlaceholder": "Enter model name (e.g. gpt-5-turbo)",
-      "modelWhitelistNotFound": "Model not found",
-      "modelWhitelistSearchPlaceholder": "Search model name...",
-      "modelWhitelistSelectAll": "Select All ({count})",
-      "modelWhitelistSelected": "Selected {count} models",
-      "modelWhitelistSelectedOnly": "Only allow selected {count} models. Requests for other models won't be routed to this provider.",
-      "name": {
-        "label": "Provider Name *",
-        "placeholder": "e.g. Zhipu"
-      },
-      "namePlaceholder": "Enter provider name",
-      "openDuration": "Circuit Break Duration (minutes)",
-      "openDurationDesc": "How long before auto entering half-open state",
-      "openDurationPlaceholder": "30",
-      "priority": "Priority",
-      "priorityDesc": "Lower number = higher priority (0 is highest). System only selects from highest priority providers. Recommendation: Main=0, Backup=1, Emergency=2",
-      "priorityLabel": "Priority",
-      "priorityPlaceholder": "0",
-      "providerGroupDesc": "Provider group tag. Only users with matching providerGroup can use this provider. Example: Set to \"premium\" to allow only providerGroup=\"premium\" users",
-      "providerGroupLabel": "Provider Group",
-      "providerGroupPlaceholder": "e.g. premium, economy",
-      "providerName": "Provider Name",
-      "providerNamePlaceholder": "e.g. Zhipu",
-      "providerNameRequired": "Provider Name *",
-      "providerType": "Provider Type",
-      "providerTypeDesc": "Select the API format type for the provider.",
-      "providerTypeDisabledNote": "Note: Gemini CLI and OpenAI Compatible types are under development",
-      "proxy": "Proxy",
-      "proxyAddressFormats": "Supported formats:",
-      "proxyAddressLabel": "Proxy Address",
-      "proxyAddressOptional": "(Optional)",
-      "proxyAddressPlaceholder": "e.g. http://proxy.example.com:8080 or socks5://127.0.0.1:1080",
-      "proxyConfig": "Proxy Configuration",
-      "proxyConfigDesc": "Configure proxy server to improve provider connectivity (supports HTTP, HTTPS, SOCKS4, SOCKS5)",
-      "proxyConfigNone": "Not configured",
-      "proxyConfigSummary": "Proxy configured",
-      "proxyConfigSummaryFallback": " (fallback enabled)",
-      "proxyConfigured": "Proxy configured",
-      "proxyFallback": "Proxy Fallback",
-      "proxyFallbackDesc": "When enabled, auto try direct connection on proxy failure",
-      "proxyFallbackLabel": "Fallback to direct on proxy failure",
-      "proxyNotConfigured": "Not configured",
-      "proxyTestButton": "Test Connection",
-      "proxyTestDesc": "Test provider URL access via configured proxy (uses HEAD request, no quota consumption)",
-      "proxyTestFailed": "Connection Failed",
-      "proxyTestFillUrl": "Please fill in provider URL first",
-      "proxyTestLabel": "Connection Test",
-      "proxyTestNetworkError": "Network error: {error}",
-      "proxyTestProxyError": "Proxy error: {error}",
-      "proxyTestResponseTime": "Response time: {time}",
-      "proxyTestResultConnectionMethod": "Connection method: {via}",
-      "proxyTestResultConnectionMethodDirect": "Direct",
-      "proxyTestResultConnectionMethodProxy": "Proxy",
-      "proxyTestResultErrorType": "Error type: {type}",
-      "proxyTestResultFailed": "Connection failed",
-      "proxyTestResultMessage": "{message}",
-      "proxyTestResultResponseTime": "Response time: {time}ms",
-      "proxyTestResultStatusCode": "Status code: {code}",
-      "proxyTestResultSuccess": "Connection successful {via}",
-      "proxyTestStatusCode": "| Status code: {code}",
-      "proxyTestSuccess": "Connection Successful",
-      "proxyTestTesting": "Testing...",
-      "proxyTestTimeout": "Connection timeout (5s). Please check:\n1. Is proxy server accessible\n2. Are proxy address and port correct\n3. Are proxy credentials correct",
-      "proxyTestViaDirect": "(direct)",
-      "proxyTestViaProxy": "(via proxy)",
-      "proxyUrl": "Proxy Address",
-      "proxyUrlPlaceholder": "e.g. http://proxy.example.com:8080 or socks5://127.0.0.1:1080",
-      "rateLimitConfig": "Rate Limit Configuration",
-      "rateLimitConfigNone": "Unlimited",
-      "rateLimitConfigSummary": "5h: ${fiveHour}, Weekly: ${weekly}, Monthly: ${monthly}, Concurrent: {concurrent}",
-      "remark": "Remark",
-      "remarkPlaceholder": "Optional: Add notes...",
-      "removeRedirect": "Remove Redirect",
-      "routingConfig": "Routing Configuration",
-      "routingConfigNone": "Not configured",
-      "routingConfigSummary": "{models} model whitelist, {redirects} redirects",
-      "scheduleParams": "Scheduling Parameters",
-      "searchClear": "Clear search",
-      "searchPlaceholder": "Search provider name, URL, remark...",
-      "selectProviderType": "Select provider type",
-      "sort": "Sort Providers",
-      "sortByCost": "By Cost",
-      "sortByCreated": "By Created (New-Old)",
-      "sortByName": "By Name (A-Z)",
-      "sortByPriority": "By Priority (High-Low)",
-      "sortByWeight": "By Weight (High-Low)",
-      "sourceModel": "Source Model Name",
-      "sourceModelPlaceholder": "e.g. claude-sonnet-4-5-20250929",
-      "sourceModelRequired": "Source model name cannot be empty",
-      "successThreshold": "Recovery Threshold (times)",
-      "successThresholdDesc": "How many successes in half-open state to fully recover",
-      "successThresholdPlaceholder": "2",
-      "targetModel": "Target Model Name",
-      "targetModelPlaceholder": "e.g. glm-4.6",
-      "targetModelRequired": "Target model name cannot be empty",
-      "testProxy": "Test Connection",
-      "testProxyFailed": "Failed to test proxy connection",
-      "testProxyFailedError": "Connection test failed:",
-      "testProxySuccess": "Proxy connection successful",
-      "validUrlRequired": "Please enter a valid API address",
-      "websiteUrl": {
-        "label": "Provider Website",
-        "placeholder": "https://example.com",
-        "desc": "Provider official website for quick access"
-      },
-      "websiteUrlDesc": "Provider website URL for quick access",
-      "websiteUrlInvalid": "Please enter a valid provider website URL",
-      "websiteUrlPlaceholder": "https://example.com",
-      "weight": "Weight",
-      "weightDesc": "Weighted random probability. Within same priority, higher weight = higher selection probability. E.g. weights 1:2:3 = probabilities 16%:33%:50%",
-      "weightLabel": "Weight",
-      "weightPlaceholder": "1",
-      "title": {
-        "create": "Add Provider",
-        "edit": "Edit Provider"
-      },
-      "dialogDescription": "Configure provider details and advanced settings.",
-      "url": {
-        "label": "API Address *",
-        "placeholder": "e.g. https://open.bigmodel.cn/api/anthropic"
-      },
-      "key": {
-        "label": "API Key",
-        "leaveEmpty": "(Leave empty to keep unchanged)",
-        "placeholder": "Enter API Key",
-        "leaveEmptyDesc": "Leave empty to keep existing key",
-        "currentKey": "Current key: {key}"
-      },
-      "buttons": {
-        "expandAll": "Expand All Advanced Settings",
-        "collapseAll": "Collapse All Advanced Settings",
-        "submit": "Confirm Add",
-        "submitting": "Adding...",
-        "update": "Confirm Update",
-        "updating": "Updating...",
-        "delete": "Delete"
-      },
-      "common": {
-        "core": "Core"
-      },
-      "sections": {
-        "routing": {
-          "title": "Routing",
-          "summary": {
-            "models": "{count} whitelisted models",
-            "redirects": "{count} redirects",
-            "none": "Not configured"
-          },
-          "providerType": {
-            "label": "Provider Type",
-            "desc": "(determines scheduling policy)",
-            "placeholder": "Select provider type"
-          },
-          "providerTypeDesc": "Choose the API format type of the provider.",
-          "providerTypeDisabledNote": "Note: OpenAI Compatible is under development and currently unavailable",
-          "modelRedirects": {
-            "label": "Model Redirects",
-            "optional": "(optional)"
-          },
-          "joinClaudePool": {
-            "label": "Join Claude Routing Pool",
-            "desc": "When enabled, this provider will participate in load balancing with Claude-type providers",
-            "help": "Available only when there is a redirect mapping to claude-* models. When users request claude-* models, this provider also joins scheduling."
-          },
-          "preserveClientIp": {
-            "label": "Forward client IP",
-            "desc": "Pass x-forwarded-for / x-real-ip to upstream providers (may expose real client IP)",
-            "help": "Keep off by default for privacy. Enable only when upstream must see the end-user IP."
-          },
-          "modelWhitelist": {
-            "title": "Model Allowlist",
-            "desc": "Restrict which models this provider can serve. By default, a provider can serve all models of its type.",
-            "label": "Allowed Models",
-            "optional": "(optional)",
-            "allowAll": "✓ Allow all models (recommended)",
-            "selectedOnly": "Only the selected {count} models are allowed. Other models will not be routed to this provider.",
-            "moreModels": "+{count} more"
-          },
-          "scheduleParams": {
-            "title": "Scheduling",
-            "priority": {
-              "label": "Priority",
-              "placeholder": "0",
-              "desc": "Lower value = higher priority (0 is highest). The system only chooses from the highest priority tier. Suggested: primary=0, standby=1, emergency=2"
-            },
-            "weight": {
-              "label": "Weight",
-              "placeholder": "1",
-              "desc": "Weighted random. Within the same priority, higher weight increases selection probability. Example 1:2:3 ≈ 16%:33%:50%"
-            },
-            "costMultiplier": {
-              "label": "Cost Multiplier",
-              "placeholder": "1.0",
-              "desc": "Cost multiplier. Official provider = 1.0, 20% cheaper = 0.8, 20% more expensive = 1.2 (up to 4 decimals)"
-            },
-            "group": {
-              "label": "Provider Group",
-              "placeholder": "e.g. premium, economy",
-              "desc": "Group tag. Only users whose providerGroup matches can use this provider. Example: set to \"premium\" to serve users with providerGroup=\"premium\" only"
-            }
-          },
-          "cacheTtl": {
-            "label": "Cache TTL Override",
-            "options": {
-              "inherit": "No override (follow client)",
-              "5m": "5 minutes",
-              "1h": "1 hour"
-            },
-            "desc": "Force prompt cache TTL; only affects requests with cache_control."
-          },
-          "context1m": {
-            "label": "1M Context Window",
-            "options": {
-              "inherit": "Inherit (follow client request)",
-              "forceEnable": "Force Enable (for supported models)",
-              "disabled": "Disabled"
-            },
-            "desc": "Configure 1M context window support. Only affects Sonnet models (claude-sonnet-4-5, claude-sonnet-4). Tiered pricing applies when enabled."
-          },
-          "codexOverrides": {
-            "reasoningEffort": {
-              "label": "Reasoning Effort Override",
-              "help": "Controls how much reasoning effort the model uses before answering. \"inherit\" follows the client request; other values force override reasoning.effort. Note: \"none\" is only supported on GPT-5.1 models; \"xhigh\" is only supported on GPT-5.1-Codex-Max. Using an unsupported value will cause an upstream error.",
-              "options": {
-                "inherit": "No override (follow client)",
-                "minimal": "minimal",
-                "low": "low",
-                "medium": "medium (default)",
-                "high": "high",
-                "xhigh": "xhigh (GPT-5.1-Codex-Max only)",
-                "none": "none (GPT-5.1 only)"
-              }
-            },
-            "reasoningSummary": {
-              "label": "Reasoning Summary Override",
-              "help": "Controls whether the Responses API returns reasoning summaries. \"auto\" returns a condensed summary, \"detailed\" returns a more comprehensive one. \"inherit\" follows the client request.",
-              "options": {
-                "inherit": "No override (follow client)",
-                "auto": "auto",
-                "detailed": "detailed"
-              }
-            },
-            "textVerbosity": {
-              "label": "Text Verbosity Override",
-              "help": "Controls how verbose the model output is. \"low\" is concise, \"high\" is verbose. \"inherit\" follows the client request.",
-              "options": {
-                "inherit": "No override (follow client)",
-                "low": "low",
-                "medium": "medium (default)",
-                "high": "high"
-              }
-            },
-            "parallelToolCalls": {
-              "label": "Parallel Tool Calls Override",
-              "help": "Controls whether parallel tool calls are allowed. \"inherit\" follows the client request. Disabling may reduce tool-call concurrency.",
-              "options": {
-                "inherit": "No override (follow client)",
-                "true": "Force enable",
-                "false": "Force disable"
-              }
-            }
-          }
-        },
-        "rateLimit": {
-          "title": "Rate Limit",
-          "summary": {
-            "fiveHour": "5h: ${amount}",
-            "daily": "Day: ${amount} (reset ${resetTime})",
-            "weekly": "Week: ${amount}",
-            "monthly": "Month: ${amount}",
-            "total": "Total: ${amount}",
-            "concurrent": "Concurrent: {count}",
-            "none": "Unlimited"
-          },
-          "limit5h": {
-            "label": "5h Spend Limit (USD)",
-            "placeholder": "Leave empty for unlimited"
-          },
-          "limitDaily": {
-            "label": "Daily Spend Limit (USD)",
-            "placeholder": "Leave empty for unlimited"
-          },
-          "dailyResetMode": {
-            "label": "Daily Reset Mode",
-            "options": {
-              "fixed": "Fixed Time Reset",
-              "rolling": "Rolling Window (24h)"
-            },
-            "desc": {
-              "fixed": "Reset quota at a fixed time each day",
-              "rolling": "Reset 24 hours after first API call"
-            }
-          },
-          "dailyResetTime": {
-            "label": "Daily Reset Time (HH:mm)"
-          },
-          "limitWeekly": {
-            "label": "Weekly Spend Limit (USD)",
-            "placeholder": "Leave empty for unlimited"
-          },
-          "limitMonthly": {
-            "label": "Monthly Spend Limit (USD)",
-            "placeholder": "Leave empty for unlimited"
-          },
-          "limitTotal": {
-            "label": "Total Spend Limit (USD)",
-            "placeholder": "Leave empty for unlimited"
-          },
-          "limitConcurrent": {
-            "label": "Concurrent Sessions Limit",
-            "placeholder": "0 means unlimited"
-          }
-        },
-        "circuitBreaker": {
-          "title": "Circuit Breaker",
-          "summary": "{failureThreshold} failures / {openDuration} min break / {successThreshold} successes to recover / {maxRetryAttempts} attempts per provider",
-          "desc": "Automatically break on consecutive failures to protect overall service quality",
-          "failureThreshold": {
-            "label": "Failure Threshold",
-            "placeholder": "5",
-            "desc": "Number of consecutive failures to trigger break"
-          },
-          "openDuration": {
-            "label": "Break Duration (minutes)",
-            "placeholder": "30",
-            "desc": "Time before switching to half-open"
-          },
-          "successThreshold": {
-            "label": "Recovery Threshold",
-            "placeholder": "2",
-            "desc": "Number of successes in half-open to fully recover"
-          },
-          "maxRetryAttempts": {
-            "label": "Max Attempts Per Provider",
-            "placeholder": "2",
-            "desc": "Total tries (including the first call) before switching providers. Leave empty to use the system default."
-          }
-        },
-        "proxy": {
-          "title": "Proxy",
-          "summary": {
-            "configured": "Proxy configured",
-            "fallback": " (fallback enabled)",
-            "none": "Not configured"
-          },
-          "desc": "Configure a proxy to improve connectivity (HTTP, HTTPS, SOCKS4, SOCKS5 supported)",
-          "url": {
-            "label": "Proxy URL",
-            "optional": "(optional)",
-            "placeholder": "e.g. http://proxy.example.com:8080 or socks5://127.0.0.1:1080",
-            "formats": "Supported formats:"
-          },
-          "fallback": {
-            "label": "Fallback to direct on proxy failure",
-            "desc": "When enabled, will try direct connection if proxy fails"
-          },
-          "test": {
-            "label": "Connectivity Test",
-            "desc": "Test accessing provider URL via proxy (HEAD request, no credits consumed)"
-          }
-        },
-        "timeout": {
-          "title": "Timeout Configuration",
-          "summary": "First byte: {streaming}s | Stream interval: {idle}s | Non-streaming: {nonStreaming}s",
-          "desc": "Configure request timeout duration, 0 means disable timeout",
-          "streamingFirstByte": {
-            "label": "Streaming First Byte Timeout (seconds)",
-            "placeholder": "30",
-            "desc": "Streaming request first byte timeout, range 1-120 seconds, default 30 seconds",
-            "core": "true"
-          },
-          "streamingIdle": {
-            "label": "Streaming Idle Timeout (seconds)",
-            "placeholder": "60",
-            "desc": "Streaming request idle timeout, range 60-600 seconds, enter 0 to disable (prevent mid-stream stalling)",
-            "core": "true"
-          },
-          "nonStreamingTotal": {
-            "label": "Non-streaming Total Timeout (seconds)",
-            "placeholder": "600",
-            "desc": "Non-streaming request total timeout, range 60-1200 seconds, default 600 seconds (10 minutes)",
-            "core": "true"
-          },
-          "disableHint": "Set to 0 to disable the timeout (for canary rollback scenarios only, not recommended)"
-        },
-        "apiTest": {
-          "title": "Provider Model Test",
-          "summary": "Verify provider & model connectivity",
-          "desc": "Validate whether the selected provider type and model respond correctly. Defaults to the routing configuration unless overridden.",
-          "testLabel": "Provider Model Test"
-        },
-        "codexStrategy": {
-          "title": "Codex Instructions Policy",
-          "summary": {
-            "auto": "Auto (recommended)",
-            "force": "Force official",
-            "keep": "Pass-through"
-          },
-          "desc": "Control how to handle the instructions field in Codex requests; affects gateway compatibility",
-          "select": {
-            "label": "Strategy",
-            "placeholder": "Select a strategy",
-            "auto": {
-              "label": "Auto (recommended)",
-              "desc": "Pass through client instructions; on 400 error, retry with official prompt"
-            },
-            "force": {
-              "label": "Force official",
-              "desc": "Always use official Codex CLI instructions (~4000+ chars)"
-            },
-            "keep": {
-              "label": "Pass-through",
-              "desc": "Always pass through client instructions, no auto retry (for permissive gateways)"
-            }
-          },
-          "hint": "Hint: Some strict Codex gateways (e.g. 88code, foxcode) require official instructions. Choose \"Auto\" or \"Force official\"."
-        },
-        "mcpPassthrough": {
-          "title": "MCP Passthrough Configuration",
-          "summary": {
-            "none": "Disabled",
-            "minimax": "Minimax",
-            "glm": "GLM",
-            "custom": "Custom (Reserved)"
-          },
-          "desc": "When enabled, pass through MCP tool calls to specified AI provider (e.g. minimax for image recognition, web search)",
-          "select": {
-            "label": "Passthrough Type",
-            "none": {
-              "label": "Disabled",
-              "desc": "Do not enable MCP passthrough (default)"
-            },
-            "minimax": {
-              "label": "Minimax",
-              "desc": "Pass through to minimax MCP service (supports image recognition, web search, etc.)"
-            },
-            "glm": {
-              "label": "GLM",
-              "desc": "Pass through to GLM MCP service (supports image analysis, video analysis, etc.)"
-            },
-            "custom": {
-              "label": "Custom",
-              "desc": "Pass through to custom MCP service (reserved, not implemented yet)"
-            },
-            "placeholder": "Select passthrough type"
-          },
-          "hint": "Hint: MCP passthrough allows Claude Code client to use tool capabilities provided by third-party AI providers (e.g. image recognition, web search)",
-          "urlLabel": "MCP Passthrough URL",
-          "urlPlaceholder": "https://api.minimaxi.com",
-          "urlDesc": "MCP service base URL. Leave empty to auto-extract from provider URL",
-          "urlAuto": "Auto-extracted: {url}"
-        }
-      },
-      "providerTypes": {
-        "claude": "Claude (Anthropic Messages API)",
-        "claudeAuth": "Claude (Anthropic Auth Token)",
-        "codex": "Codex (Response API)",
-        "gemini": "Gemini (Google Gemini API)",
-        "geminiCli": "Gemini CLI",
-        "geminiCliDisabled": " - in development",
-        "openaiCompatible": "OpenAI Compatible",
-        "openaiCompatibleDisabled": " - in development"
-      },
-      "deleteDialog": {
-        "title": "Delete Provider",
-        "description": "Are you sure you want to delete provider \"{name}\"? This action cannot be undone.",
-        "cancel": "Cancel",
-        "confirm": "Confirm Delete"
-      },
-      "failureThresholdConfirmDialog": {
-        "title": "Confirm Special Configuration",
-        "descriptionDisabledPrefix": "You are setting the circuit breaker failure threshold to ",
-        "descriptionDisabledValue": "0",
-        "descriptionDisabledMiddle": ", which means ",
-        "descriptionDisabledAction": "disabling the circuit breaker",
-        "descriptionDisabledSuffix": ". The provider will not be circuit-broken due to consecutive failures.",
-        "descriptionHighValuePrefix": "You are setting the circuit breaker failure threshold to ",
-        "descriptionHighValueSuffix": ", which is a high value and may cause the provider to be circuit-broken only after many failures.",
-        "confirmQuestion": "Are you sure you want to save this configuration?",
-        "cancel": "Cancel",
-        "confirm": "Confirm Save"
-      },
-      "errors": {
-        "invalidUrl": "Please enter a valid API address",
-        "invalidWebsiteUrl": "Please enter a valid provider website URL",
-        "groupTagTooLong": "Provider group tags are too long (max {max} chars total)",
-        "addFailed": "Failed to add provider",
-        "updateFailed": "Failed to update provider",
-        "deleteFailed": "Failed to delete provider"
-      },
-      "success": {
-        "created": "Provider added successfully",
-        "createdDesc": "Provider \"{name}\" has been added"
-      }
-    },
-    "guide": {
-      "after": "After:",
-      "before": "Before:",
-      "bestPracticesConcurrent": "• Concurrent Control: Set session concurrency by provider API limits",
-      "bestPracticesCost": "• Cost Multiplier: Official=1.0, Self-hosted can be 0.8-1.2",
-      "bestPracticesLimit": "• Limit Settings: Set 5h, 7d, 30d limits based on budget",
-      "bestPracticesPriority": "• Priority Settings: Core providers=0, Backup=1-3",
-      "bestPracticesTitle": "Best Practices",
-      "bestPracticesWeight": "• Weight Config: Set weight by capacity (higher capacity = higher weight)",
-      "circuitBreaker": "Circuit Breaker Check",
-      "circuitBreakerOpen": "A filtered, remaining: B, C, D",
-      "circuitBreakerRecovery": "A automatically recovers to half-open after 60 seconds",
-      "circuitBreakerRecovery5h": "Auto recovery after 5-hour sliding window",
-      "costOptimize": "2️⃣ Cost Optimization: Within same priority, lower cost multiplier has higher probability",
-      "costSort": "Cost-based Sorting Fallback",
-      "costSortExample": "All providers: A (default), B (premium), C (premium), D (economy)",
-      "costSortProb": "Lower cost C has higher selection probability",
-      "costSortResult": "After sorting: C (0.8x), A (1.0x)",
-      "decision": "Decision:",
-      "group": "User Group Filtering",
-      "groupDesc": "If user has provider group specified, system prioritizes selection from that group",
-      "groupDowngrade": "Log warning and select from global provider pool",
-      "groupExample": "User configured providerGroup = 'premium'",
-      "groupFallback": "If no available providers in user group, fallback to all providers",
-      "groupFiltered": "Select only from A and C, B and D filtered",
-      "groupUnavailable": "All providers in user group 'vip' are disabled or over limit",
-      "health": "Health Filtering (Circuit Breaker + Rate Limit)",
-      "healthCheck": "Check if B is enabled and healthy",
-      "healthCheckAmountLimit": "Check if spending exceeds limits (5h, 7d, 30d)",
-      "healthCheckAmountLimitExample": "Provider B has $10 limit (5h), $9.8 consumed",
-      "healthCheckCircuit": "Provider A failed 5 times, circuit breaker: open",
-      "healthCheckConcurrent": "Check if current active session count exceeds limit",
-      "healthCheckConcurrentExample": "Provider C limit 2, currently 2 active sessions",
-      "healthFilter": "3️⃣ Health Filtering: Auto skip circuit-broken or over-limit providers",
-      "healthFiltered": "B filtered (near limit), remaining: C, D",
-      "healthFiltered2": "C filtered (full), remaining: D",
-      "history": "Check Request History",
-      "historyDesc": "Query providers used by this API Key in last 10 seconds",
-      "priority": "Priority Layering",
-      "priorityExample": "4 enabled providers with different priorities",
-      "priorityFirst": "1️⃣ Priority First: Select only from highest priority (lowest number) providers",
-      "priorityResult": "Filtered to highest priority (0) providers: A, C",
-      "priorityStep": "System first filters by priority, selecting only from highest priority providers",
-      "randomResult": "Finally selected C randomly",
-      "randomSelect": "Weighted Random",
-      "reset": "Manual Circuit Breaker Reset",
-      "resetSuccess": "Circuit breaker reset",
-      "scenario1Desc": "System first filters by priority, selecting only from highest priority providers",
-      "scenario1Step1": "Initial State",
-      "scenario1Step1After": "Filtered to highest priority (0) providers: A, C",
-      "scenario1Step1Before": "Provider A (priority 0), B (priority 1), C (priority 0), D (priority 2)",
-      "scenario1Step1Decision": "Select only from A and C, B and D filtered out",
-      "scenario1Step1Desc": "4 enabled providers with different priorities",
-      "scenario1Step2": "Cost Sorting",
-      "scenario1Step2After": "After sorting: C (0.8x), A (1.0x)",
-      "scenario1Step2Before": "A (cost 1.0x), C (cost 0.8x)",
-      "scenario1Step2Decision": "Lower cost C has higher selection probability",
-      "scenario1Step2Desc": "Within same priority, sort by cost multiplier low to high",
-      "scenario1Step3": "Weighted Random",
-      "scenario1Step3After": "C has 75% probability, A has 25%",
-      "scenario1Step3Before": "C (weight 3), A (weight 1)",
-      "scenario1Step3Decision": "Finally randomly selected C",
-      "scenario1Step3Desc": "Use weight for random selection, higher weight = higher probability",
-      "scenario1Title": "Priority Layering",
-      "scenario2Desc": "If user has provider group specified, system prioritizes selection from that group",
-      "scenario2Step1": "Check User Group",
-      "scenario2Step1After": "Filtered to 'premium' group: B, C",
-      "scenario2Step1Before": "All providers: A (default), B (premium), C (premium), D (economy)",
-      "scenario2Step1Decision": "Select only from B and C",
-      "scenario2Step1Desc": "User configured providerGroup = 'premium'",
-      "scenario2Step2": "Group Fallback",
-      "scenario2Step2After": "Fallback to all enabled providers: A, B, C, D",
-      "scenario2Step2Before": "All providers in user group 'vip' disabled or over limit",
-      "scenario2Step2Decision": "Log warning and select from global provider pool",
-      "scenario2Step2Desc": "If no available providers in user group, fallback to all providers",
-      "scenario2Title": "User Group Filtering",
-      "scenario3Desc": "System auto filters circuit-broken or over-limit providers",
-      "scenario3Step1": "Circuit Breaker Check",
-      "scenario3Step1After": "A filtered, remaining: B, C, D",
-      "scenario3Step1Before": "Provider A failed 5 times, circuit breaker: open",
-      "scenario3Step1Decision": "A auto recovers to half-open after 60s",
-      "scenario3Step1Desc": "Circuit breaker opens after 5 consecutive failures, unavailable for 60s",
-      "scenario3Step2": "Amount Rate Limit",
-      "scenario3Step2After": "B filtered (near limit), remaining: C, D",
-      "scenario3Step2Before": "Provider B 5h limit $10, consumed $9.8",
-      "scenario3Step2Decision": "Auto recovery after 5h sliding window",
-      "scenario3Step2Desc": "Check if spending exceeds limits (5h, 7d, 30d)",
-      "scenario3Step3": "Concurrent Session Limit",
-      "scenario3Step3After": "C filtered (full), remaining: D",
-      "scenario3Step3Before": "Provider C concurrent limit 2, currently 2 active sessions",
-      "scenario3Step3Decision": "Auto release after session expiry (5 min)",
-      "scenario3Step3Desc": "Check if active session count exceeds configured concurrent limit",
-      "scenario3Title": "Health Filtering (Circuit Breaker + Rate Limit)",
-      "scenario4Desc": "Consecutive chats prioritize using same provider, leveraging Claude context cache",
-      "scenario4Step1": "Check Request History",
-      "scenario4Step1After": "Check if B is enabled and healthy",
-      "scenario4Step1Before": "Last request used provider B",
-      "scenario4Step1Decision": "B available, reuse directly, skip random selection",
-      "scenario4Step1Desc": "Query providers used by this API Key in last 10 seconds",
-      "scenario4Step2": "Reuse Invalidation",
-      "scenario4Step2After": "Enter normal selection flow",
-      "scenario4Step2Before": "Last used provider B disabled or circuit-broken",
-      "scenario4Step2Decision": "Select from other available providers",
-      "scenario4Step2Desc": "If last used provider unavailable, reselect",
-      "scenario4Title": "Session Reuse Mechanism",
-      "scenariosTitle": "Interactive Scenario Demos",
-      "session": "Session Reuse Mechanism",
-      "sessionDesc": "If the last used provider is unavailable, reselect",
-      "sessionExample": "Last request used provider B",
-      "sessionExpired": "Session automatically released after expiration (5 minutes)",
-      "sessionFallback": "Select from other available providers",
-      "sessionLastUsed": "B is available, reuse directly, skip random selection",
-      "sessionReuse": "4️⃣ Session Reuse: Consecutive chats reuse same provider, saving context costs",
-      "sessionUnavailable": "Last used provider B is disabled or circuit-broken",
-      "step": "Step",
-      "title": "Core Principles",
-      "weight": "Weighted random selection based on weight",
-      "weightCalc": "C has 75% selection probability, A has 25%",
-      "weightExample": "C (weight 3), A (weight 1)"
-    },
-    "keyLoading": "Loading...",
-    "noProviders": "No providers configured",
-    "noProvidersDesc": "Add your first API provider",
-    "notFound": "No matching providers found",
-    "official": "Official",
-    "resetCircuit": "Circuit breaker reset",
-    "resetCircuitDesc": "Provider \"{name}\" circuit breaker status cleared",
-    "resetCircuitFailed": "Failed to reset circuit breaker",
-    "scheduling": "Scheduling Strategy Details",
-    "schedulingDesc": "Understand how provider selection works with priority layering, session reuse, load balancing and failover",
-    "searchNoResults": "No matching providers found",
-    "searchResults": "Found {count} matching providers",
-    "section": {
-      "description": "Configure upstream provider rate limiting and concurrent session limits. Leave empty for unlimited.",
-      "leaderboard": "Leaderboard",
-      "title": "Provider Management"
-    },
-    "filter": {
-      "status": {
-        "all": "Any status",
-        "active": "Active",
-        "inactive": "Inactive"
-      },
-      "groups": {
-        "label": "Groups:",
-        "all": "All",
-        "default": "default"
-      },
-      "circuitBroken": "Circuit Broken"
-    },
-    "subtitle": "Provider Management",
-    "subtitleDesc": "Configure upstream provider rate limiting and concurrent session limits. Leave empty for unlimited.",
-    "title": "Provider Management",
-    "todayUsage": "Today's Usage",
-    "todayUsageCount": "{count} times",
-    "toggleFailed": "Toggle failed",
-    "toggleSuccess": "Provider {status}",
-    "toggleSuccessDesc": "Provider \"{name}\" status updated",
-    "updateFailed": "Failed to update provider",
-    "viewKey": "View Complete API Key",
-    "viewKeyDesc": "Please keep it safe and don't share it with others",
-    "sort": {
-      "byName": "By Name (A-Z)",
-      "byPriority": "By Priority (High-Low)",
-      "byWeight": "By Weight (High-Low)",
-      "byActualPriority": "By Actual Selection Priority",
-      "byCreatedAt": "By Created Time (New-Old)",
-      "placeholder": "Sort Providers"
-    },
-    "search": {
-      "placeholder": "Search provider name, URL, notes...",
-      "clear": "Clear search",
-      "found": "Found {count} matching provider(s)",
-      "notFound": "No matching providers found",
-      "showing": "Showing {filtered} / {total} providers"
-    }
-  },
-  "sensitiveWords": {
-    "add": "Add Sensitive Word",
-    "addFailed": "Failed to create sensitive word",
-    "addSuccess": "Sensitive word created successfully",
-    "cacheStats": "Cache stats: Contains({containsCount}) Exact({exactCount}) Regex({regexCount})",
-    "confirmDelete": "Are you sure you want to delete the sensitive word \"{word}\"?",
-    "delete": "Delete Sensitive Word",
-    "deleteFailed": "Delete failed",
-    "deleteSuccess": "Sensitive word deleted successfully",
-    "description": "Configure sensitive word filtering rules to block requests with sensitive content.",
-    "dialog": {
-      "addDescription": "Configure sensitive word filtering rules. Matched requests will not be forwarded upstream.",
-      "addTitle": "Add Sensitive Word",
-      "creating": "Creating...",
-      "descriptionLabel": "Description",
-      "descriptionPlaceholder": "Optional: Add description...",
-      "editDescription": "Modify sensitive word configuration. Changes will automatically refresh the cache.",
-      "editTitle": "Edit Sensitive Word",
-      "matchTypeContains": "Contains Match - Block if text contains this word",
-      "matchTypeExact": "Exact Match - Block only if exact match",
-      "matchTypeLabel": "Match Type *",
-      "matchTypeRegex": "Regular Expression - Support complex pattern matching",
-      "saving": "Saving...",
-      "wordLabel": "Sensitive Word *",
-      "wordPlaceholder": "Enter sensitive word...",
-      "wordRequired": "Please enter a sensitive word"
-    },
-    "disable": "Sensitive word disabled",
-    "edit": "Edit Sensitive Word",
-    "editFailed": "Failed to update sensitive word",
-    "editSuccess": "Sensitive word updated successfully",
-    "emptyState": "No sensitive words yet. Click 'Add Sensitive Word' in the top right to start configuration.",
-    "enable": "Sensitive word enabled",
-    "refreshCache": "Refresh Cache",
-    "refreshCacheFailed": "Failed to refresh cache",
-    "refreshCacheSuccess": "Cache refreshed successfully, loaded {count} sensitive words",
-    "section": {
-      "description": "Requests blocked by sensitive words will not be forwarded upstream and will not be charged. Supports contains matching, exact matching, and regex patterns.",
-      "title": "Sensitive Words List"
-    },
-    "table": {
-      "actions": "Actions",
-      "createdAt": "Created At",
-      "description": "Description",
-      "matchType": "Match Type",
-      "matchTypeContains": "Contains Match",
-      "matchTypeExact": "Exact Match",
-      "matchTypeRegex": "Regular Expression",
-      "status": "Status",
-      "word": "Sensitive Word"
-    },
-    "title": "Sensitive Words Management",
-    "toggleFailed": "Toggle failed",
-    "toggleFailedError": "Toggle failed:"
-  },
-  "requestFilters": {
-    "nav": "Request Filters",
-    "title": "Request Filters",
-    "description": "Configure header removal/override and body replacement rules to sanitize requests before forwarding upstream.",
-    "add": "Add Filter",
-    "addSuccess": "Filter created",
-    "addFailed": "Failed to create filter",
-    "edit": "Edit Filter",
-    "editSuccess": "Filter updated",
-    "editFailed": "Failed to update filter",
-    "delete": "Delete Filter",
-    "deleteSuccess": "Filter deleted",
-    "deleteFailed": "Delete failed",
-    "enable": "Enabled",
-    "disable": "Disabled",
-    "confirmDelete": "Delete filter \"{name}\"?",
-    "empty": "No filters yet. Click Add Filter to configure.",
-    "refreshCache": "Refresh Cache",
-    "refreshSuccess": "Cache refreshed, loaded {count} filters",
-    "refreshFailed": "Refresh failed",
-    "dialog": {
-      "createTitle": "Add Filter",
-      "editTitle": "Edit Filter",
-      "name": "Name",
-      "scope": "Scope",
-      "action": "Action",
-      "target": "Target field/path",
-      "replacement": "Replacement (optional)",
-      "description": "Description (optional)",
-      "priority": "Priority",
-      "matchType": "Match Type",
-      "matchTypeContains": "Contains",
-      "matchTypeExact": "Exact",
-      "matchTypeRegex": "Regex",
-      "jsonPathPlaceholder": "e.g. messages.0.content or data.items[0].token",
-      "targetPlaceholder": "Header name or text/path",
-      "replacementPlaceholder": "String or JSON, leave blank to clear",
-      "save": "Save",
-      "saving": "Saving...",
-      "validation": {
-        "fieldRequired": "Name and target are required"
-      },
-      "bindingType": "Apply To",
-      "bindingGlobal": "All Providers (Global)",
-      "bindingProviders": "Specific Providers",
-      "bindingGroups": "Provider Groups",
-      "selectProviders": "Select providers...",
-      "selectGroups": "Select groups...",
-      "searchProviders": "Search providers...",
-      "searchGroups": "Search groups...",
-      "noProvidersFound": "No providers found",
-      "noGroupsFound": "No groups found",
-      "providersSelected": "{count} provider(s) selected",
-      "groupsSelected": "{count} group(s) selected",
-      "loading": "Loading...",
-      "clear": "Clear",
-      "selectAll": "Select All"
-    },
-    "table": {
-      "name": "Name",
-      "scope": "Scope",
-      "action": "Action",
-      "target": "Target",
-      "replacement": "Replacement",
-      "priority": "Priority",
-      "apply": "Apply",
-      "status": "Status",
-      "createdAt": "Created At",
-      "actions": "Actions"
-    },
-    "scopeLabel": {
-      "header": "Header",
-      "body": "Body"
-    },
-    "actionLabel": {
-      "remove": "Remove Header",
-      "set": "Set Header",
-      "json_path": "JSON Path Replace",
-      "text_replace": "Text Replace"
-    },
-    "applyToAll": "Applied to all requests",
-    "providers": "Providers",
-    "groups": "Groups"
-  },
-  "errorRules": {
-    "nav": "Error Rules",
-    "title": "Error Rules Management",
-    "description": "Manage client error rules that should not trigger automatic retries. When configured, errors matching these rules will be returned directly to users without retrying or counting toward provider circuit breaker thresholds.",
-    "section": {
-      "title": "Error Rules List"
-    },
-    "tester": {
-      "title": "Error Rule Tester",
-      "description": "Input an error message to check if it matches configured rules and see the final response.",
-      "inputLabel": "Test Error Message",
-      "inputPlaceholder": "Enter an error message to test...",
-      "testButton": "Run Test",
-      "testing": "Testing...",
-      "matched": "Matched an error rule",
-      "notMatched": "No rule matched",
-      "finalResponse": "Override response to return",
-      "ruleInfo": "Matched rule",
-      "noRule": "No rule matched",
-      "category": "Category",
-      "pattern": "Pattern",
-      "matchType": "Match type",
-      "overrideStatusCode": "Override status code",
-      "testFailed": "Test failed, please try again",
-      "messageRequired": "Please enter an error message to test",
-      "warnings": "Configuration Warnings",
-      "statusCodeOnlyOverride": "Only status code will be overridden, response body will use upstream error"
-    },
-    "add": "Add Error Rule",
-    "addSuccess": "Error rule created successfully",
-    "addFailed": "Failed to create error rule",
-    "edit": "Edit Error Rule",
-    "editSuccess": "Error rule updated successfully",
-    "editFailed": "Failed to update error rule",
-    "delete": "Delete Error Rule",
-    "deleteSuccess": "Error rule deleted successfully",
-    "deleteFailed": "Delete failed",
-    "enable": "Error rule enabled",
-    "disable": "Error rule disabled",
-    "toggleFailed": "Toggle failed",
-    "toggleFailedError": "Toggle failed:",
-    "refreshCache": "Sync Rules",
-    "refreshCacheSuccess": "Rules synced successfully, loaded {count} error rules",
-    "refreshCacheFailed": "Failed to sync rules",
-    "cacheStats": "Cached {totalCount} error rules",
-    "emptyState": "No error rules yet. Click 'Add Error Rule' in the top right to start configuration.",
-    "confirmDelete": "Are you sure you want to delete error rule \"{pattern}\"?",
-    "dialog": {
-      "addTitle": "Add Error Rule",
-      "addDescription": "Configure error message regex patterns. Matched errors will be identified as non-retryable client errors.",
-      "editTitle": "Edit Error Rule",
-      "editDescription": "Modify error rule configuration. Changes will automatically refresh the cache.",
-      "patternLabel": "Regex Pattern *",
-      "patternPlaceholder": "Enter regular expression...",
-      "patternRequired": "Please enter regex pattern",
-      "patternHint": "Supports JavaScript regex syntax, e.g.: prompt is too long|invalid.*request",
-      "categoryLabel": "Rule Category *",
-      "categoryPlaceholder": "Select rule category",
-      "categoryRequired": "Please select rule category",
-      "categoryHint": "Choose the error category for classification and statistics",
-      "descriptionLabel": "Description",
-      "descriptionPlaceholder": "Optional: Add description...",
-      "invalidRegex": "Invalid regex syntax",
-      "regexTester": "Regex Tester",
-      "testMessageLabel": "Test Message",
-      "testMessagePlaceholder": "Enter error message to test...",
-      "matchSuccess": "Match Successful",
-      "matchFailed": "No Match",
-      "invalidPattern": "Invalid Regex",
-      "matchedText": "Matched Text",
-      "defaultRuleHint": "Default rule pattern cannot be modified",
-      "enableOverride": "Enable Error Override",
-      "enableOverrideHint": "When enabled, you can customize the error response and status code returned to clients. Original errors are still logged to the database. Currently only supports Claude API error format.",
-      "overrideResponseLabel": "Override Response (JSON)",
-      "overrideResponsePlaceholder": "{\n  \"type\": \"error\",\n  \"error\": {\n    \"type\": \"invalid_request_error\",\n    \"message\": \"Your custom message\"\n  }\n}",
-      "overrideResponseHint": "Leave empty to only override status code.",
-      "overrideStatusCodeLabel": "Override Status Code (Optional)",
-      "overrideStatusCodePlaceholder": "e.g. 400",
-      "overrideStatusCodeHint": "Leave empty to use upstream status code. Range: 400-599.",
-      "useTemplate": "Claude Error Template",
-      "useTemplateConfirm": "Existing content will be replaced by the template. Continue?",
-      "validJson": "JSON format is valid",
-      "invalidJson": "Invalid JSON format",
-      "invalidStatusCode": "Status code must be between 400-599",
-      "creating": "Creating...",
-      "saving": "Saving..."
-    },
-    "table": {
-      "pattern": "Regex Pattern",
-      "category": "Rule Category",
-      "description": "Description",
-      "status": "Status",
-      "default": "Default",
-      "isEnabled": "Enabled Status",
-      "isDefault": "Default Rule",
-      "createdAt": "Created At",
-      "actions": "Actions"
-    },
-    "form": {
-      "fields": {
-        "pattern": "Regex Pattern",
-        "category": "Rule Category",
-        "description": "Description"
-      },
-      "placeholders": {
-        "pattern": "e.g. prompt is too long",
-        "category": "Select category",
-        "description": "Optional: Add description..."
-      },
-      "labels": {
-        "pattern": "Regex Pattern *",
-        "category": "Rule Category *",
-        "description": "Description",
-        "isEnabled": "Enabled Status"
-      }
-    },
-    "actions": {
-      "add": "Add",
-      "edit": "Edit",
-      "delete": "Delete",
-      "refresh": "Refresh",
-      "test": "Test",
-      "messages": {
-        "success": "Operation successful",
-        "error": "Operation failed"
-      }
-    },
-    "validation": {
-      "patternRequired": "Please enter regex pattern",
-      "categoryRequired": "Please select rule category",
-      "patternInvalid": "Invalid regex syntax",
-      "redosRisk": "Regex has ReDoS risk, please simplify pattern",
-      "patternTooComplex": "Regex is too complex"
-    },
-    "categories": {
-      "prompt_limit": "Prompt Length Limit",
-      "content_filter": "Content Filter",
-      "pdf_limit": "PDF Page Limit",
-      "thinking_error": "Thinking Format Error",
-      "parameter_error": "Parameter Validation Failed",
-      "invalid_request": "Invalid Request",
-      "cache_limit": "Cache Control Limit"
-    },
-    "regexTester": {
-      "title": "Regex Tester",
-      "testMessage": "Test Message",
-      "testMessagePlaceholder": "Enter error message to test...",
-      "matchResult": "Match Result",
-      "matched": "Matched",
-      "notMatched": "Not Matched",
-      "test": "Test"
-    },
-    "defaultRules": {
-      "cannotDelete": "Default rules cannot be deleted",
-      "cannotDisable": "Recommend keeping default rules enabled"
-    }
-  },
-  "mcpPassthroughConfig": "MCP Passthrough Configuration",
-  "mcpPassthroughConfigNone": "Disabled",
-  "mcpPassthroughConfigMinimax": "Minimax",
-  "mcpPassthroughConfigGlm": "GLM",
-  "mcpPassthroughConfigCustom": "Custom (Reserved)",
-  "mcpPassthroughDesc": "When enabled, pass through MCP tool calls to specified AI provider (e.g. minimax for image recognition, web search)",
-  "mcpPassthroughSelect": "Passthrough Type",
-  "mcpPassthroughNoneLabel": "Disabled",
-  "mcpPassthroughNoneDesc": "Do not enable MCP passthrough (default)",
-  "mcpPassthroughMinimaxLabel": "Minimax",
-  "mcpPassthroughMinimaxDesc": "Pass through to minimax MCP service (supports image recognition, web search, etc.)",
-  "mcpPassthroughGlmLabel": "GLM",
-  "mcpPassthroughGlmDesc": "Pass through to GLM MCP service (supports image analysis, video analysis, etc.)",
-  "mcpPassthroughCustomLabel": "Custom",
-  "mcpPassthroughCustomDesc": "Pass through to custom MCP service (reserved, not implemented yet)",
-  "mcpPassthroughHint": "Hint: MCP passthrough allows Claude Code client to use tool capabilities provided by third-party AI providers (e.g. image recognition, web search)",
-  "mcpPassthroughUrlLabel": "MCP Passthrough URL",
-  "mcpPassthroughUrlPlaceholder": "https://api.minimaxi.com",
-  "mcpPassthroughUrlDesc": "MCP service base URL. Leave empty to auto-extract from provider URL",
-  "mcpPassthroughUrlAuto": "Auto-extracted: {url}"
-}

+ 51 - 0
messages/en/settings/clientVersions.json

@@ -0,0 +1,51 @@
+{
+  "description": "Manage client version requirements to ensure users use latest stable version. VSCode plugin and CLI are managed separately.",
+  "empty": {
+    "description": "No active users using recognizable clients in past 7 days",
+    "title": "No client data available"
+  },
+  "features": {
+    "activeWindow": "Active Window: ",
+    "activeWindowDesc": "Only counts users with requests in the past 7 days",
+    "autoDetect": "System automatically detects the latest stable version (GA version) for each client type",
+    "blockOldVersion": "Users with old versions will receive HTTP 400 error and cannot continue using the service",
+    "errorMessage": "Error message includes current version and required upgrade version",
+    "gaRule": "GA Rule: ",
+    "gaRuleDesc": "A version is considered GA when used by more than 1 user",
+    "recommendation": "Recommendation: ",
+    "recommendationDesc": "Monitor the version distribution below and confirm new version stability before enabling.",
+    "title": "Feature Description",
+    "whatHappens": "What happens when enabled:"
+  },
+  "section": {
+    "distribution": {
+      "description": "Shows client version info for active users in past 7 days. Each client type independently tracks GA versions.",
+      "title": "Client Version Distribution"
+    },
+    "settings": {
+      "description": "When enabled, system automatically detects client version and blocks old version users.",
+      "title": "Update Reminder Settings"
+    }
+  },
+  "table": {
+    "currentGA": "Current GA Version: ",
+    "internalType": "Internal Type: ",
+    "lastActive": "Last Active",
+    "latest": "Latest",
+    "needsUpgrade": "Needs Upgrade",
+    "noUsers": "No user data available",
+    "status": "Status",
+    "unknown": "Unknown",
+    "user": "User",
+    "usersCount": "{count} users",
+    "version": "Current Version"
+  },
+  "title": "Client Update Reminder",
+  "toggle": {
+    "description": "When enabled, system will block requests from old version clients",
+    "disableSuccess": "Client version check disabled",
+    "enable": "Enable Update Reminder",
+    "enableSuccess": "Client version check enabled",
+    "toggleFailed": "Update failed"
+  }
+}

+ 31 - 0
messages/en/settings/common.json

@@ -0,0 +1,31 @@
+{
+  "cancel": "Cancel",
+  "completed": "Completed",
+  "confirm": "Confirm",
+  "copied": "Key copied to clipboard",
+  "copy": "Copy",
+  "copyFailed": "Copy failed",
+  "create": "Create",
+  "creating": "Creating...",
+  "delete": "Delete",
+  "disabled": "Disabled",
+  "edit": "Edit",
+  "empty": "No matching results found",
+  "enabled": "Enabled",
+  "error": "Unknown error",
+  "failed": "Failed",
+  "loading": "Loading...",
+  "none": "None (No users using this version)",
+  "refresh": "Refresh",
+  "reset": "Reset",
+  "save": "Save",
+  "saving": "Saving...",
+  "submit": "Submit",
+  "success": "Success",
+  "test": "Test",
+  "testing": "Testing...",
+  "unlimited": "Unlimited",
+  "unlimited_desc": "Unlimited",
+  "update": "Update",
+  "updating": "Updating..."
+}

+ 89 - 0
messages/en/settings/config.json

@@ -0,0 +1,89 @@
+{
+  "autoCleanup": "Auto Log Cleanup",
+  "autoCleanupDesc": "Automatically clean up historical log data on schedule to free up database storage space.",
+  "description": "Manage system basic parameters that affect site display and statistics behavior.",
+  "form": {
+    "allowGlobalView": "Allow Global Usage View",
+    "allowGlobalViewDesc": "When disabled, regular users can only view their own key usage statistics in the dashboard.",
+    "autoCleanupSaved": "Auto cleanup configuration saved",
+    "billingModelSource": "Billing Model Source",
+    "billingModelSourceDesc": "Configure which model to use for billing when model redirection occurs. 'Before Redirection' uses the original model requested by the user, 'After Redirection' uses the actual model called.",
+    "billingModelSourceOptions": {
+      "original": "Before Redirection (Original Model)",
+      "redirected": "After Redirection (Actual Model)"
+    },
+    "billingModelSourcePlaceholder": "Select billing model source",
+    "cleanupBatchSize": "Batch Size",
+    "cleanupBatchSizeDesc": "Number of records to delete per batch (range: 1000-100000, recommended 10000)",
+    "cleanupBatchSizePlaceholder": "10000",
+    "cleanupBatchSizeRequired": "Batch Size *",
+    "cleanupRetentionDays": "Retention Days",
+    "cleanupRetentionDaysDesc": "Logs older than this number of days will be automatically cleaned (range: 1-365 days)",
+    "cleanupRetentionDaysPlaceholder": "30",
+    "cleanupRetentionDaysRequired": "Retention Days *",
+    "cleanupSchedule": "Cleanup Schedule",
+    "cleanupScheduleCronDesc": "Cron expression, default: 0 2 * * * (2 AM daily)",
+    "cleanupScheduleCronExample": "Example: 0 3 * * 0 (3 AM every Sunday)",
+    "cleanupScheduleDesc": "Select the execution schedule for automatic cleanup",
+    "cleanupScheduleLabel": "Execution Time (Cron)",
+    "cleanupSchedulePlaceholder": "0 2 * * *",
+    "cleanupScheduleRequired": "Execution Time (Cron) *",
+    "configUpdated": "System settings updated. The page will refresh to apply currency display changes.",
+    "currencies": {
+      "CNY": "¥ Chinese Yuan (CNY)",
+      "EUR": "€ Euro (EUR)",
+      "GBP": "£ British Pound (GBP)",
+      "HKD": "HK$ Hong Kong Dollar (HKD)",
+      "JPY": "¥ Japanese Yen (JPY)",
+      "KRW": "₩ South Korean Won (KRW)",
+      "SGD": "S$ Singapore Dollar (SGD)",
+      "TWD": "NT$ New Taiwan Dollar (TWD)",
+      "USD": "$ US Dollar (USD)"
+    },
+    "currencyDisplay": "Currency Display Unit",
+    "currencyDisplayDesc": "After modification, all pages and API interfaces will use the corresponding currency symbol (symbol only, no exchange rate conversion).",
+    "currencyDisplayPlaceholder": "Select currency unit",
+    "enableAutoCleanup": "Enable Auto Cleanup",
+    "enableAutoCleanupDesc": "Automatically clean up historical log data on schedule",
+    "enableHttp2": "Enable HTTP/2",
+    "enableHttp2Desc": "When enabled, proxy requests will prefer HTTP/2 protocol. Automatically falls back to HTTP/1.1 on failure.",
+    "enableResponseFixer": "Enable Response Fixer",
+    "enableResponseFixerDesc": "Automatically repairs common upstream response issues (encoding, SSE, truncated JSON). Enabled by default.",
+    "enableThinkingSignatureRectifier": "Enable Thinking Signature Rectifier",
+    "enableThinkingSignatureRectifierDesc": "When Anthropic providers return thinking signature incompatibility or invalid request errors, automatically removes incompatible thinking blocks and retries once against the same provider (enabled by default).",
+    "interceptAnthropicWarmupRequests": "Intercept Warmup Requests (Anthropic)",
+    "interceptAnthropicWarmupRequestsDesc": "When enabled, Claude Code warmup probe requests will be answered by CCH directly to avoid upstream provider calls; the request is logged for audit but is not billed, not rate-limited, and excluded from statistics.",
+    "keepDays": "Retention Days",
+    "keepDaysDesc": "Clean up logs older than this number of days",
+    "responseFixerFixEncoding": "Fix encoding issues",
+    "responseFixerFixEncodingDesc": "Removes BOM/null bytes and normalizes invalid UTF-8.",
+    "responseFixerFixSseFormat": "Fix SSE format",
+    "responseFixerFixSseFormatDesc": "Adds missing data: prefix, normalizes line endings, and fixes common field formatting.",
+    "responseFixerFixTruncatedJson": "Fix truncated JSON",
+    "responseFixerFixTruncatedJsonDesc": "Closes unclosed braces/quotes, removes trailing commas, and fills missing values with null when needed.",
+    "saveConfig": "Save Configuration",
+    "saveError": "Save failed",
+    "saveFailed": "Save failed",
+    "saveSettings": "Save Settings",
+    "saveSuccess": "Saved successfully",
+    "siteTitle": "Site Title",
+    "siteTitleDesc": "Used to set browser tab title and system default display name.",
+    "siteTitlePlaceholder": "e.g. Claude Code Hub",
+    "siteTitleRequired": "Site title cannot be empty",
+    "verboseProviderError": "Verbose Provider Error",
+    "verboseProviderErrorDesc": "When enabled, return detailed error messages when all providers are unavailable (including provider count, rate limit reasons, etc.); when disabled, only return a simple error code."
+  },
+  "section": {
+    "autoCleanup": {
+      "description": "Automatically clean up historical log data on schedule to free up database storage space.",
+      "title": "Auto Log Cleanup"
+    },
+    "siteParams": {
+      "description": "Configure site title, currency display unit, and dashboard statistics display policy.",
+      "title": "Site Parameters"
+    }
+  },
+  "siteSettings": "Site Parameters",
+  "siteSettingsDesc": "Configure site title, currency display unit, and dashboard statistics display policy.",
+  "title": "Basic Configuration"
+}

+ 133 - 0
messages/en/settings/data.json

@@ -0,0 +1,133 @@
+{
+  "cleanup": {
+    "backupRecommendation": "Recommendation: Export database backup before cleanup in case recovery is needed.",
+    "button": "Clean Logs",
+    "cancel": "Cancel",
+    "cleaning": "Cleaning...",
+    "confirm": "Confirm Cleanup",
+    "confirmTitle": "Confirm Log Cleanup",
+    "confirmWarning": "This operation will permanently delete all log records from {range} and cannot be recovered.",
+    "descriptionWarning": "Clean up historical log data to free up database storage. Note: Statistics data will be retained, but log details will be permanently deleted.",
+    "error": "Failed to clean logs",
+    "failed": "Cleanup failed",
+    "logsDeleted": "✗ Log details will be deleted (request/response content, error info, etc.)",
+    "previewCount": "Will delete {count} log records",
+    "previewError": "Unable to get preview",
+    "previewLoading": "Counting...",
+    "range": {
+      "180days": "Logs older than 6 months (180 days)",
+      "30days": "Logs older than 1 month (30 days)",
+      "7days": "Logs older than 1 week (7 days)",
+      "90days": "Logs older than 3 months (90 days)"
+    },
+    "rangeDescription": {
+      "180days": "6 months ago",
+      "30days": "1 month ago",
+      "7days": "1 week ago",
+      "90days": "3 months ago",
+      "default": "{days} days ago"
+    },
+    "rangeLabel": "Cleanup Range",
+    "statisticsRetained": "✓ Statistics data will be retained (for trend analysis)",
+    "successMessage": "Successfully cleaned {count} log records ({batches} batches, took {duration}s)",
+    "willClean": "Will clean all log records from {range}"
+  },
+  "description": "Manage database backup and recovery with full data import/export and log cleanup.",
+  "export": {
+    "button": "Export Database",
+    "descriptionFull": "Export complete database backup file (.dump format) for data migration or recovery. Backup uses PostgreSQL custom format, auto-compressed and compatible with different database versions.",
+    "error": "Failed to export database",
+    "exporting": "Exporting...",
+    "failed": "Export failed",
+    "successMessage": "Database exported successfully!"
+  },
+  "guide": {
+    "items": {
+      "cleanup": {
+        "description": "Physically delete historical log data (irreversible). Statistics table will be retained. Recommend exporting database backup before cleanup.",
+        "title": "Log Cleanup"
+      },
+      "environment": {
+        "description": "This feature requires Docker Compose deployment. Local development may not support it.",
+        "title": "Environment Requirements"
+      },
+      "format": {
+        "description": "Uses PostgreSQL custom format (.dump), auto-compressed and compatible with different database versions.",
+        "title": "Backup Format"
+      },
+      "merge": {
+        "description": "Retains existing data and attempts to insert backup data. Primary key conflicts may cause import failure.",
+        "title": "Merge Mode"
+      },
+      "overwrite": {
+        "description": "Deletes all existing data before importing, ensuring database matches backup exactly. Best for complete recovery.",
+        "title": "Overwrite Mode"
+      },
+      "safety": {
+        "description": "Before importing, recommend exporting current database as backup to avoid data loss.",
+        "title": "Security Recommendation"
+      }
+    },
+    "title": "Usage Instructions and Precautions"
+  },
+  "import": {
+    "backupFile": "Backup file:",
+    "backupRecommendation": "Recommend exporting current database as backup before proceeding.",
+    "button": "Import Database",
+    "cancel": "Cancel",
+    "cleanFirstDescription": "Delete all existing data before importing to ensure database matches backup exactly. If unchecked, will attempt to merge data but may fail due to primary key conflicts.",
+    "cleanFirstLabel": "Clear existing data (overwrite mode)",
+    "confirm": "Confirm Import",
+    "confirmMerge": "You selected 'Merge Mode', which will attempt to import backup while keeping existing data.",
+    "confirmOverwrite": "You selected 'Overwrite Mode', which will delete all existing data before importing backup.",
+    "confirmTitle": "Confirm Database Import",
+    "descriptionFull": "Restore database from backup file. Supports PostgreSQL custom format (.dump) backup files.",
+    "error": "Failed to import database",
+    "errorUnknown": "Unknown error",
+    "failedMessage": "Data import failed",
+    "fileError": "Please select .dump format backup file",
+    "fileSelected": "Selected: {name} ({size} MB)",
+    "importing": "Importing...",
+    "noFileSelected": "Please select backup file first",
+    "parseError": "Failed to parse response data",
+    "progressTitle": "Import Progress",
+    "selectFileLabel": "Select Backup File",
+    "streamError": "Cannot read response stream",
+    "streamInterrupted": "Data stream unexpectedly interrupted",
+    "streamInterruptedDesc": "Import progress did not complete normally. Please check the logs and verify data integrity. Re-import if needed.",
+    "successCleanModeDesc": "All data has been successfully restored. Refresh your browser if the page displays incorrectly.",
+    "successMergeModeDesc": "Data has been successfully imported and merged. Refresh your browser if the page displays incorrectly.",
+    "successMessage": "Data import completed!",
+    "successWithWarnings": "Data import completed (with warnings)",
+    "successWithWarningsDesc": "Data has been successfully imported, but some existing objects were skipped. Refresh your browser or restart the application if the page displays incorrectly.",
+    "warningMerge": "Note: Import may fail if primary key conflicts exist.",
+    "warningOverwrite": "Warning: This action is irreversible, all current data will be permanently deleted!"
+  },
+  "section": {
+    "cleanup": {
+      "description": "Clean up historical log data to free up database storage. Note: Statistics data will be retained, but log details will be permanently deleted.",
+      "title": "Log Cleanup"
+    },
+    "export": {
+      "description": "Export complete database backup file (.dump format) for data migration or recovery.",
+      "title": "Data Export"
+    },
+    "import": {
+      "description": "Restore database from backup file. Supports PostgreSQL custom format (.dump) backup files.",
+      "title": "Data Import"
+    },
+    "status": {
+      "description": "View current database connection status and basic information.",
+      "title": "Database Status"
+    }
+  },
+  "status": {
+    "connected": "Database connected",
+    "error": "Failed to get database status",
+    "loading": "Loading...",
+    "retry": "Retry",
+    "tables": "{count} tables",
+    "unavailable": "Database unavailable"
+  },
+  "title": "Data Management"
+}

+ 157 - 0
messages/en/settings/errorRules.json

@@ -0,0 +1,157 @@
+{
+  "actions": {
+    "add": "Add",
+    "delete": "Delete",
+    "edit": "Edit",
+    "messages": {
+      "error": "Operation failed",
+      "success": "Operation successful"
+    },
+    "refresh": "Refresh",
+    "test": "Test"
+  },
+  "add": "Add Error Rule",
+  "addFailed": "Failed to create error rule",
+  "addSuccess": "Error rule created successfully",
+  "cacheStats": "Cached {totalCount} error rules",
+  "categories": {
+    "cache_limit": "Cache Control Limit",
+    "content_filter": "Content Filter",
+    "invalid_request": "Invalid Request",
+    "parameter_error": "Parameter Validation Failed",
+    "pdf_limit": "PDF Page Limit",
+    "prompt_limit": "Prompt Length Limit",
+    "thinking_error": "Thinking Format Error"
+  },
+  "confirmDelete": "Are you sure you want to delete error rule \"{pattern}\"?",
+  "defaultRules": {
+    "cannotDelete": "Default rules cannot be deleted",
+    "cannotDisable": "Recommend keeping default rules enabled"
+  },
+  "delete": "Delete Error Rule",
+  "deleteFailed": "Delete failed",
+  "deleteSuccess": "Error rule deleted successfully",
+  "description": "Manage client error rules that should not trigger automatic retries. When configured, errors matching these rules will be returned directly to users without retrying or counting toward provider circuit breaker thresholds.",
+  "dialog": {
+    "addDescription": "Configure error message regex patterns. Matched errors will be identified as non-retryable client errors.",
+    "addTitle": "Add Error Rule",
+    "categoryHint": "Choose the error category for classification and statistics",
+    "categoryLabel": "Rule Category *",
+    "categoryPlaceholder": "Select rule category",
+    "categoryRequired": "Please select rule category",
+    "creating": "Creating...",
+    "defaultRuleHint": "Default rule pattern cannot be modified",
+    "descriptionLabel": "Description",
+    "descriptionPlaceholder": "Optional: Add description...",
+    "editDescription": "Modify error rule configuration. Changes will automatically refresh the cache.",
+    "editTitle": "Edit Error Rule",
+    "enableOverride": "Enable Error Override",
+    "enableOverrideHint": "When enabled, you can customize the error response and status code returned to clients. Original errors are still logged to the database. Currently only supports Claude API error format.",
+    "invalidJson": "Invalid JSON format",
+    "invalidPattern": "Invalid Regex",
+    "invalidRegex": "Invalid regex syntax",
+    "invalidStatusCode": "Status code must be between 400-599",
+    "matchFailed": "No Match",
+    "matchSuccess": "Match Successful",
+    "matchedText": "Matched Text",
+    "overrideResponseHint": "Leave empty to only override status code.",
+    "overrideResponseLabel": "Override Response (JSON)",
+    "overrideResponsePlaceholder": "{\n  \"type\": \"error\",\n  \"error\": {\n    \"type\": \"invalid_request_error\",\n    \"message\": \"Your custom message\"\n  }\n}",
+    "overrideStatusCodeHint": "Leave empty to use upstream status code. Range: 400-599.",
+    "overrideStatusCodeLabel": "Override Status Code (Optional)",
+    "overrideStatusCodePlaceholder": "e.g. 400",
+    "patternHint": "Supports JavaScript regex syntax, e.g.: prompt is too long|invalid.*request",
+    "patternLabel": "Regex Pattern *",
+    "patternPlaceholder": "Enter regular expression...",
+    "patternRequired": "Please enter regex pattern",
+    "regexTester": "Regex Tester",
+    "saving": "Saving...",
+    "testMessageLabel": "Test Message",
+    "testMessagePlaceholder": "Enter error message to test...",
+    "useTemplate": "Claude Error Template",
+    "useTemplateConfirm": "Existing content will be replaced by the template. Continue?",
+    "validJson": "JSON format is valid"
+  },
+  "disable": "Error rule disabled",
+  "edit": "Edit Error Rule",
+  "editFailed": "Failed to update error rule",
+  "editSuccess": "Error rule updated successfully",
+  "emptyState": "No error rules yet. Click 'Add Error Rule' in the top right to start configuration.",
+  "enable": "Error rule enabled",
+  "form": {
+    "fields": {
+      "category": "Rule Category",
+      "description": "Description",
+      "pattern": "Regex Pattern"
+    },
+    "labels": {
+      "category": "Rule Category *",
+      "description": "Description",
+      "isEnabled": "Enabled Status",
+      "pattern": "Regex Pattern *"
+    },
+    "placeholders": {
+      "category": "Select category",
+      "description": "Optional: Add description...",
+      "pattern": "e.g. prompt is too long"
+    }
+  },
+  "nav": "Error Rules",
+  "refreshCache": "Sync Rules",
+  "refreshCacheFailed": "Failed to sync rules",
+  "refreshCacheSuccess": "Rules synced successfully, loaded {count} error rules",
+  "regexTester": {
+    "matchResult": "Match Result",
+    "matched": "Matched",
+    "notMatched": "Not Matched",
+    "test": "Test",
+    "testMessage": "Test Message",
+    "testMessagePlaceholder": "Enter error message to test...",
+    "title": "Regex Tester"
+  },
+  "section": {
+    "title": "Error Rules List"
+  },
+  "table": {
+    "actions": "Actions",
+    "category": "Rule Category",
+    "createdAt": "Created At",
+    "default": "Default",
+    "description": "Description",
+    "isDefault": "Default Rule",
+    "isEnabled": "Enabled Status",
+    "pattern": "Regex Pattern",
+    "status": "Status"
+  },
+  "tester": {
+    "category": "Category",
+    "description": "Input an error message to check if it matches configured rules and see the final response.",
+    "finalResponse": "Override response to return",
+    "inputLabel": "Test Error Message",
+    "inputPlaceholder": "Enter an error message to test...",
+    "matchType": "Match type",
+    "matched": "Matched an error rule",
+    "messageRequired": "Please enter an error message to test",
+    "noRule": "No rule matched",
+    "notMatched": "No rule matched",
+    "overrideStatusCode": "Override status code",
+    "pattern": "Pattern",
+    "ruleInfo": "Matched rule",
+    "statusCodeOnlyOverride": "Only status code will be overridden, response body will use upstream error",
+    "testButton": "Run Test",
+    "testFailed": "Test failed, please try again",
+    "testing": "Testing...",
+    "title": "Error Rule Tester",
+    "warnings": "Configuration Warnings"
+  },
+  "title": "Error Rules Management",
+  "toggleFailed": "Toggle failed",
+  "toggleFailedError": "Toggle failed:",
+  "validation": {
+    "categoryRequired": "Please select rule category",
+    "patternInvalid": "Invalid regex syntax",
+    "patternRequired": "Please enter regex pattern",
+    "patternTooComplex": "Regex is too complex",
+    "redosRisk": "Regex has ReDoS risk, please simplify pattern"
+  }
+}

+ 17 - 0
messages/en/settings/errors.json

@@ -0,0 +1,17 @@
+{
+  "addFailed": "Failed to add provider",
+  "addSuccess": "Add succeeded",
+  "deleteFailed": "Failed to delete provider",
+  "deleteSuccess": "Delete succeeded",
+  "editFailed": "Failed to update provider",
+  "editSuccess": "Update succeeded",
+  "loadFailed": "Failed to load notification settings",
+  "saveFailed": "Save failed",
+  "saveFailed_error": "Failed to save settings",
+  "saveSuccess": "Save succeeded",
+  "syncFailed": "Sync failed",
+  "syncSuccess": "Sync succeeded",
+  "testFailed": "Test failed",
+  "testFailedRetry": "Test failed, please retry",
+  "unknownError": "An exception occurred during the operation"
+}

+ 101 - 0
messages/en/settings/index.ts

@@ -0,0 +1,101 @@
+import clientVersions from "./clientVersions.json";
+import common from "./common.json";
+import config from "./config.json";
+import data from "./data.json";
+import errorRules from "./errorRules.json";
+import errors from "./errors.json";
+import logs from "./logs.json";
+import nav from "./nav.json";
+import notifications from "./notifications.json";
+import prices from "./prices.json";
+import requestFilters from "./requestFilters.json";
+import sensitiveWords from "./sensitiveWords.json";
+import strings from "./strings.json";
+
+import providersAutoSort from "./providers/autoSort.json";
+import providersFilter from "./providers/filter.json";
+import providersGuide from "./providers/guide.json";
+import providersInlineEdit from "./providers/inlineEdit.json";
+import providersList from "./providers/list.json";
+import providersSchedulingDialog from "./providers/schedulingDialog.json";
+import providersSearch from "./providers/search.json";
+import providersSection from "./providers/section.json";
+import providersSort from "./providers/sort.json";
+import providersStrings from "./providers/strings.json";
+import providersTypes from "./providers/types.json";
+
+import providersFormApiTest from "./providers/form/apiTest.json";
+import providersFormButtons from "./providers/form/buttons.json";
+import providersFormCommon from "./providers/form/common.json";
+import providersFormDeleteDialog from "./providers/form/deleteDialog.json";
+import providersFormErrors from "./providers/form/errors.json";
+import providersFormFailureThresholdConfirmDialog from "./providers/form/failureThresholdConfirmDialog.json";
+import providersFormKey from "./providers/form/key.json";
+import providersFormMaxRetryAttempts from "./providers/form/maxRetryAttempts.json";
+import providersFormModelRedirect from "./providers/form/modelRedirect.json";
+import providersFormModelSelect from "./providers/form/modelSelect.json";
+import providersFormName from "./providers/form/name.json";
+import providersFormProviderTypes from "./providers/form/providerTypes.json";
+import providersFormProxyTest from "./providers/form/proxyTest.json";
+import providersFormSections from "./providers/form/sections.json";
+import providersFormStrings from "./providers/form/strings.json";
+import providersFormSuccess from "./providers/form/success.json";
+import providersFormTitle from "./providers/form/title.json";
+import providersFormUrl from "./providers/form/url.json";
+import providersFormUrlPreview from "./providers/form/urlPreview.json";
+import providersFormWebsiteUrl from "./providers/form/websiteUrl.json";
+
+const providersForm = {
+  ...providersFormStrings,
+  apiTest: providersFormApiTest,
+  buttons: providersFormButtons,
+  common: providersFormCommon,
+  deleteDialog: providersFormDeleteDialog,
+  errors: providersFormErrors,
+  failureThresholdConfirmDialog: providersFormFailureThresholdConfirmDialog,
+  key: providersFormKey,
+  maxRetryAttempts: providersFormMaxRetryAttempts,
+  modelRedirect: providersFormModelRedirect,
+  modelSelect: providersFormModelSelect,
+  name: providersFormName,
+  providerTypes: providersFormProviderTypes,
+  proxyTest: providersFormProxyTest,
+  sections: providersFormSections,
+  success: providersFormSuccess,
+  title: providersFormTitle,
+  url: providersFormUrl,
+  urlPreview: providersFormUrlPreview,
+  websiteUrl: providersFormWebsiteUrl,
+};
+
+const providers = {
+  ...providersStrings,
+  autoSort: providersAutoSort,
+  filter: providersFilter,
+  form: providersForm,
+  guide: providersGuide,
+  inlineEdit: providersInlineEdit,
+  list: providersList,
+  schedulingDialog: providersSchedulingDialog,
+  search: providersSearch,
+  section: providersSection,
+  sort: providersSort,
+  types: providersTypes,
+};
+
+export default {
+  nav,
+  common,
+  config,
+  providers,
+  prices,
+  sensitiveWords,
+  requestFilters,
+  logs,
+  data,
+  clientVersions,
+  notifications,
+  errors,
+  errorRules,
+  ...strings,
+};

+ 54 - 0
messages/en/settings/logs.json

@@ -0,0 +1,54 @@
+{
+  "description": "Dynamically adjust system log level to control logging verbosity in real-time.",
+  "form": {
+    "changeNotice": "Current level is {current}, will switch to {selected} after saving",
+    "currentLevel": "Current Log Level",
+    "effectiveImmediately": "Log level changes take effect immediately without service restart.",
+    "failed": "Failed to set",
+    "failedError": "Failed to set log level",
+    "fetchFailed": "Failed to fetch log level",
+    "levelGuideDebug": "Debug (Recommended for Development): Includes detailed debug info, suitable for troubleshooting",
+    "levelGuideFatal": "Fatal/Error: Only errors shown, minimal logging, suitable for high-load production",
+    "levelGuideInfo": "Info (Recommended for Production): Shows key business events (provider selection, Session reuse, price sync) + Warnings + Errors",
+    "levelGuideTitle": "Log Level Guide",
+    "levelGuideTrace": "Trace: Extremely detailed trace information, includes all details",
+    "levelGuideWarn": "Warn: Includes warnings (rate limiting, circuit breaker opening, etc.) + Errors",
+    "save": "Save Settings",
+    "saving": "Saving...",
+    "selectLevel": "Select Log Level",
+    "success": "Log level set to: {level}"
+  },
+  "levels": {
+    "debug": {
+      "description": "Debug info + All levels (Recommended for Development)",
+      "label": "Debug"
+    },
+    "error": {
+      "description": "Error messages",
+      "label": "Error"
+    },
+    "fatal": {
+      "description": "Fatal errors only",
+      "label": "Fatal"
+    },
+    "info": {
+      "description": "Key business events + Warnings + Errors (Recommended for Production)",
+      "label": "Info"
+    },
+    "trace": {
+      "description": "Extremely detailed tracing + All levels",
+      "label": "Trace"
+    },
+    "warn": {
+      "description": "Warnings + Errors",
+      "label": "Warn"
+    }
+  },
+  "section": {
+    "description": "Changes take effect immediately without service restart.",
+    "title": "Log Level Control"
+  },
+  "subtitle": "Log Level Control",
+  "subtitleDesc": "Changes take effect immediately without restart. Useful for troubleshooting in production.",
+  "title": "Log Management"
+}

+ 15 - 0
messages/en/settings/nav.json

@@ -0,0 +1,15 @@
+{
+  "apiDocs": "API Docs",
+  "clientVersions": "Updates",
+  "config": "Config",
+  "data": "Data",
+  "docs": "Documentation",
+  "errorRules": "Errors",
+  "feedback": "Feedback",
+  "logs": "Logs",
+  "notifications": "Notifications",
+  "prices": "Pricing",
+  "providers": "Providers",
+  "requestFilters": "Requests",
+  "sensitiveWords": "Filters"
+}

+ 146 - 0
messages/en/settings/notifications.json

@@ -0,0 +1,146 @@
+{
+  "bindings": {
+    "advanced": "Advanced",
+    "bindTarget": "Bind target",
+    "boundCount": "Bound: {count}",
+    "editTemplateOverride": "Edit Override",
+    "enable": "Enable",
+    "enableType": "Enable this notification",
+    "enabledCount": "Enabled: {count}",
+    "noTargets": "No push targets available.",
+    "scheduleCron": "Cron",
+    "scheduleCronPlaceholder": "e.g. 0 9 * * *",
+    "scheduleTimezone": "Timezone",
+    "templateOverride": "Template Override",
+    "templateOverrideTitle": "Edit Template Override",
+    "title": "Bindings"
+  },
+  "circuitBreaker": {
+    "description": "Send alert immediately when provider is fully circuit broken",
+    "enable": "Enable Circuit Breaker Alert",
+    "test": "Test Connection",
+    "title": "Circuit Breaker Alert",
+    "webhook": "Webhook URL",
+    "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=..."
+  },
+  "costAlert": {
+    "description": "Trigger alert when user/provider consumption exceeds quota threshold",
+    "enable": "Enable Cost Alert",
+    "interval": "Check Interval (minutes)",
+    "test": "Test Connection",
+    "threshold": "Alert Threshold",
+    "thresholdHelp": "Alert when consumption reaches {percent}% of quota",
+    "thresholdLabel": "Alert Threshold: {percent}%",
+    "title": "Cost Alert",
+    "webhook": "Webhook URL",
+    "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...",
+    "webhookTypeFeishu": "Feishu",
+    "webhookTypeUnknown": "Unknown platform. Please use WeCom or Feishu webhook URL",
+    "webhookTypeWeCom": "WeCom"
+  },
+  "dailyLeaderboard": {
+    "description": "Send daily scheduled user consumption Top N leaderboard",
+    "enable": "Enable Daily Leaderboard",
+    "test": "Test Connection",
+    "time": "Send Time",
+    "timeError": "Time format error, should be HH:mm",
+    "timePlaceholder": "09:00",
+    "title": "Daily User Consumption Leaderboard",
+    "topN": "Show Top N",
+    "webhook": "Webhook URL",
+    "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=..."
+  },
+  "description": "Configure Webhook push notifications",
+  "form": {
+    "loadError": "Failed to load notification settings",
+    "loading": "Loading...",
+    "save": "Save Settings",
+    "saveError": "Failed to save settings",
+    "saveFailed": "Save failed",
+    "saving": "Saving...",
+    "success": "Notification settings saved and tasks rescheduled",
+    "testError": "Test connection failed",
+    "testFailed": "Test failed",
+    "testFailedRetry": "Test failed, please retry",
+    "testNoResult": "Test succeeded but no result returned",
+    "testSuccess": "Test message sent",
+    "webhookRequired": "Please fill in Webhook URL first"
+  },
+  "global": {
+    "description": "Enable or disable all push notification features",
+    "enable": "Enable Push Notifications",
+    "legacyModeDescription": "You are using legacy single-URL notifications. Create a push target to switch to multi-target mode.",
+    "legacyModeTitle": "Legacy Mode",
+    "title": "Notification Master Switch"
+  },
+  "targetDialog": {
+    "createTitle": "Add Push Target",
+    "customHeaders": "Custom Headers (JSON)",
+    "customHeadersPlaceholder": "{\"X-Token\":\"...\"}",
+    "dingtalkSecret": "DingTalk Secret",
+    "dingtalkSecretPlaceholder": "Optional, used for signing",
+    "editTitle": "Edit Push Target",
+    "enable": "Enable",
+    "errors": {
+      "headersInvalidJson": "Headers must be valid JSON",
+      "headersMustBeObject": "Headers must be a JSON object",
+      "headersValueMustBeString": "Header values must be strings"
+    },
+    "name": "Target Name",
+    "namePlaceholder": "e.g. Ops Group",
+    "proxy": {
+      "fallbackToDirect": "Fallback to direct on proxy failure",
+      "title": "Proxy",
+      "toggle": "Toggle proxy settings",
+      "url": "Proxy URL",
+      "urlPlaceholder": "http://127.0.0.1:7890"
+    },
+    "selectType": "Select platform type",
+    "telegramBotToken": "Telegram Bot Token",
+    "telegramBotTokenPlaceholder": "e.g. 123456:ABCDEF...",
+    "telegramChatId": "Telegram Chat ID",
+    "telegramChatIdPlaceholder": "e.g. -1001234567890",
+    "type": "Platform Type",
+    "types": {
+      "custom": "Custom Webhook",
+      "dingtalk": "DingTalk",
+      "feishu": "Feishu",
+      "telegram": "Telegram",
+      "wechat": "WeCom"
+    },
+    "webhookUrl": "Webhook URL",
+    "webhookUrlPlaceholder": "https://example.com/webhook"
+  },
+  "targets": {
+    "add": "Add Target",
+    "bindingsSaved": "Bindings saved",
+    "created": "Target created",
+    "delete": "Delete",
+    "deleteConfirm": "Are you sure you want to delete this target? Related bindings will also be removed.",
+    "deleteConfirmTitle": "Delete Push Target",
+    "deleted": "Target deleted",
+    "description": "Manage push targets. Supports WeCom, Feishu, DingTalk, Telegram and custom Webhook.",
+    "edit": "Edit",
+    "emptyHint": "No push targets yet. Click \"Add Target\" to create one.",
+    "enable": "Enable Target",
+    "lastTestAt": "Last Test",
+    "lastTestFailed": "Test Failed",
+    "lastTestNever": "Never tested",
+    "lastTestSuccess": "Test OK",
+    "statusDisabled": "Disabled",
+    "statusEnabled": "Enabled",
+    "test": "Test",
+    "testSelectType": "Select test type",
+    "title": "Push Targets",
+    "update": "Save Target",
+    "updated": "Target updated"
+  },
+  "templateEditor": {
+    "insert": "Insert",
+    "jsonInvalid": "Invalid JSON",
+    "placeholder": "Enter JSON template...",
+    "placeholders": "Placeholders",
+    "title": "Template (JSON)"
+  },
+  "title": "Push Notifications"
+}

+ 191 - 0
messages/en/settings/prices.json

@@ -0,0 +1,191 @@
+{
+  "title": "Pricing",
+  "description": "Manage platform basic configuration and model pricing",
+  "section": {
+    "title": "Model Pricing",
+    "description": "Manage AI model pricing configuration"
+  },
+  "searchPlaceholder": "Search model name...",
+  "filters": {
+    "all": "All",
+    "local": "Local",
+    "anthropic": "Anthropic",
+    "openai": "OpenAI",
+    "vertex": "Vertex"
+  },
+  "badges": {
+    "local": "Local"
+  },
+  "capabilities": {
+    "assistantPrefill": "Assistant prefill",
+    "computerUse": "Computer use",
+    "functionCalling": "Function calling",
+    "pdfInput": "PDF input",
+    "promptCaching": "Prompt caching",
+    "reasoning": "Reasoning",
+    "responseSchema": "Response schema",
+    "toolChoice": "Tool choice",
+    "vision": "Vision",
+    "statusSupported": "Supported",
+    "statusUnsupported": "Not supported",
+    "tooltip": "{label}: {status}"
+  },
+  "sync": {
+    "button": "Sync Cloud Price Table",
+    "syncing": "Syncing...",
+    "checking": "Checking conflicts...",
+    "successWithChanges": "Price table updated: {added} added, {updated} updated, {unchanged} unchanged",
+    "successNoChanges": "Price table is up to date, no updates needed",
+    "failed": "Sync failed",
+    "failedError": "Sync failed: {error}",
+    "failedNoResult": "Price table updated but no result returned",
+    "noModels": "No model prices found",
+    "partialFailure": "Partial update succeeded, but {failed} models failed",
+    "failedModels": "Failed models: {models}",
+    "skippedConflicts": "Skipped {count} manual models"
+  },
+  "conflict": {
+    "title": "Select Items to Overwrite",
+    "description": "The following models have manual prices. Check the ones to overwrite with LiteLLM prices, unchecked ones will be kept unchanged",
+    "searchPlaceholder": "Search models...",
+    "table": {
+      "modelName": "Model",
+      "manualPrice": "Manual Price",
+      "litellmPrice": "LiteLLM Price",
+      "action": "Action"
+    },
+    "viewDiff": "View Diff",
+    "diffTitle": "Price Difference",
+    "diff": {
+      "field": "Field",
+      "manual": "Manual",
+      "litellm": "LiteLLM",
+      "inputPrice": "Input Price",
+      "outputPrice": "Output Price",
+      "imagePrice": "Image Price",
+      "provider": "Provider",
+      "mode": "Type"
+    },
+    "pagination": {
+      "showing": "Showing {from}-{to} of {total}"
+    },
+    "selectedCount": "Selected {count}/{total} models",
+    "noMatch": "No matching models found",
+    "noConflicts": "No conflicts",
+    "applyOverwrite": "Apply Overwrite",
+    "applying": "Applying..."
+  },
+  "table": {
+    "modelName": "Model Name",
+    "provider": "Provider",
+    "capabilities": "Capabilities",
+    "price": "Price",
+    "inputPrice": "Input Price ($/M)",
+    "outputPrice": "Output Price ($/M)",
+    "priceInput": "In",
+    "priceOutput": "Out",
+    "pricePerRequest": "Req",
+    "cacheReadPrice": "Cache Read ($/M)",
+    "cacheCreationPrice": "Cache Create ($/M)",
+    "cache5m": "5m",
+    "cache1h": "1h+",
+    "copyModelId": "Copy model ID",
+    "updatedAt": "Updated At",
+    "actions": "Actions",
+    "typeChat": "Chat",
+    "typeImage": "Image",
+    "typeCompletion": "Completion",
+    "typeUnknown": "Unknown",
+    "loading": "Loading...",
+    "noMatch": "No matching models found",
+    "noDataTitle": "No price data available",
+    "noDataHint": "System has built-in price table. Use buttons above to sync or update."
+  },
+  "pagination": {
+    "showing": "Showing {from}-{to} of {total}",
+    "previous": "Previous",
+    "next": "Next",
+    "perPageLabel": "Per page",
+    "perPage": "{size} per page"
+  },
+  "stats": {
+    "totalModels": "{count} models total",
+    "searchResults": "{count} search results",
+    "lastUpdated": "Last updated: {time}"
+  },
+  "dialog": {
+    "title": "Update Model Price Table",
+    "description": "Select and upload JSON or TOML file containing model pricing data",
+    "selectFile": "Click to select JSON/TOML file or drag and drop here",
+    "fileSizeLimit": "File size cannot exceed 10MB",
+    "fileSizeLimitSmall": "File size not exceeding 10MB",
+    "invalidFileType": "Please select a JSON or TOML file",
+    "fileTooLarge": "File size exceeds 10MB limit",
+    "upload": "Upload and Update",
+    "uploading": "Uploading...",
+    "updatePriceTable": "Update Price Table",
+    "updating": "Updating...",
+    "selectJson": "Select File",
+    "updateSuccess": "Price table updated successfully, {count} models updated",
+    "updateFailed": "Update failed",
+    "systemHasBuiltIn": "System has built-in price table",
+    "manualDownload": "You can also manually download",
+    "latestPriceTable": "cloud price table",
+    "andUploadViaButton": ", and upload via button above",
+    "cloudModelCountLoading": "Loading cloud model count...",
+    "cloudModelCountFailed": "Failed to load cloud model count",
+    "supportedModels": "Currently supports {count} models",
+    "results": {
+      "title": "Update Results",
+      "total": "Total: {total} models",
+      "success": "Success: {success}",
+      "failed": "Failed: {failed}",
+      "skipped": "Skipped: {skipped}",
+      "more": " (+{count})",
+      "details": "Details",
+      "viewDetails": "View detailed logs"
+    }
+  },
+  "addModel": "Add Model",
+  "editModel": "Edit Model",
+  "deleteModel": "Delete Model",
+  "addModelDescription": "Manually add a new model price configuration",
+  "editModelDescription": "Edit the model price configuration",
+  "deleteConfirm": "Are you sure you want to delete model {name}? This action cannot be undone.",
+  "form": {
+    "modelName": "Model ID",
+    "modelNamePlaceholder": "e.g., gpt-5.2-codex",
+    "modelNameRequired": "Model ID is required",
+    "displayName": "Display Name (Optional)",
+    "displayNamePlaceholder": "e.g., GPT-5.2 Codex",
+    "type": "Type",
+    "provider": "Provider",
+    "providerPlaceholder": "e.g., openai",
+    "requestPrice": "Per-call Price ($/request)",
+    "inputPrice": "Input Price ($/M tokens)",
+    "outputPrice": "Output Price ($/M tokens)",
+    "outputPriceImage": "Output Price ($/image)",
+    "cacheReadPrice": "Cache Read Price ($/M tokens)",
+    "cacheCreationPrice5m": "Cache Creation Price (5m, $/M tokens)",
+    "cacheCreationPrice1h": "Cache Creation Price (1h+, $/M tokens)"
+  },
+  "drawer": {
+    "prefillLabel": "Search existing models to prefill",
+    "prefillEmpty": "No matching models found",
+    "prefillFailed": "Search failed",
+    "promptCachingHint": "Enable if the model supports prompt caching",
+    "cachePricingTitle": "Cache Pricing"
+  },
+  "actions": {
+    "edit": "Edit",
+    "more": "More actions",
+    "delete": "Delete"
+  },
+  "toast": {
+    "createSuccess": "Model added",
+    "updateSuccess": "Model updated",
+    "deleteSuccess": "Model deleted",
+    "saveFailed": "Failed to save",
+    "deleteFailed": "Failed to delete"
+  }
+}

+ 16 - 0
messages/en/settings/providers/autoSort.json

@@ -0,0 +1,16 @@
+{
+  "button": "Auto Sort Priority",
+  "changeCount": "{count} providers will be updated",
+  "changesTitle": "Change Details",
+  "confirm": "Apply Changes",
+  "costMultiplierHeader": "Cost Multiplier",
+  "dialogDescription": "Automatically assign priority based on cost multiplier (lower cost = higher priority)",
+  "dialogTitle": "Auto Sort Provider Priority",
+  "error": "Failed to update priorities",
+  "noChanges": "No changes needed (already sorted)",
+  "priorityChangeHeader": "Priority Change",
+  "priorityHeader": "Priority",
+  "providerHeader": "Provider",
+  "providersHeader": "Providers",
+  "success": "Updated priority for {count} providers"
+}

+ 13 - 0
messages/en/settings/providers/filter.json

@@ -0,0 +1,13 @@
+{
+  "circuitBroken": "Circuit Broken",
+  "groups": {
+    "all": "All",
+    "default": "default",
+    "label": "Groups:"
+  },
+  "status": {
+    "active": "Active",
+    "all": "Any status",
+    "inactive": "Inactive"
+  }
+}

+ 157 - 0
messages/en/settings/providers/form/apiTest.json

@@ -0,0 +1,157 @@
+{
+  "apiFormat": "Provider type",
+  "apiFormatDesc": "Defaults to the routing configuration unless manually changed",
+  "chunksCount": "Received {count} chunks ({format})",
+  "chunksReceived": "Chunks received",
+  "close": "Close",
+  "copyFailed": "Failed to copy",
+  "copyFormat": {
+    "errorDetails": "Error details",
+    "message": "Message",
+    "testResult": "Test result"
+  },
+  "copyResult": "Copy Result",
+  "copySuccess": "Copied to clipboard",
+  "customConfig": "Custom",
+  "customPayloadDesc": "Enter custom JSON payload to override default request body",
+  "customPayloadPlaceholder": "{\"model\": \"...\", \"messages\": [...]}",
+  "disclaimer": {
+    "confirmConfig": "Please verify provider URL, API key, and model configuration",
+    "realRequest": "This test sends a real request to the provider and may consume a small quota",
+    "resultReference": "[IMPORTANT] Results may vary by provider and are for reference only",
+    "title": "Notice"
+  },
+  "error": "Error message",
+  "failed": "Failed",
+  "fillKeyFirst": "Please fill in API key first",
+  "fillUrlFirst": "Please fill in provider URL first",
+  "formatAnthropicMessages": "Claude (Anthropic Messages API)",
+  "formatOpenAIChat": "OpenAI Compatible",
+  "formatOpenAIResponses": "Codex (Response API)",
+  "geminiAuthFallback": {
+    "desc": "Actual proxy forwarding only uses header auth, may cause request failures",
+    "warning": "Header auth failed, using URL parameter auth"
+  },
+  "invalidUrl": "Provider URL is invalid (http/https only)",
+  "model": "Model",
+  "noResult": "Test succeeded but no result returned",
+  "presetConfig": "Preset",
+  "presetDesc": "Preset templates contain authentic CLI request patterns for relay service verification",
+  "requestConfig": "Request Configuration",
+  "response": "Response preview",
+  "responseModel": "Response model",
+  "responseTime": "Response time",
+  "resultCard": {
+    "copyText": {
+      "contentCheck": "Content Check",
+      "error": "Error",
+      "httpCheck": "HTTP Check",
+      "httpStatus": "HTTP Status",
+      "inputOutput": "Input {input} / Output {output} tokens",
+      "latency": "Latency",
+      "latencyCheck": "Latency Check",
+      "message": "Message",
+      "model": "Model",
+      "response": "Response",
+      "status": "Status",
+      "testedAt": "Tested At",
+      "usage": "Usage",
+      "validationDetails": "Validation Details"
+    },
+    "dialogTitle": "Provider Test Details",
+    "errorDetails": {
+      "title": "Error Details",
+      "type": "Error Type"
+    },
+    "judgment": "Judgment",
+    "labels": {
+      "content": "Content",
+      "error": "Error",
+      "firstByte": "First Byte",
+      "http": "HTTP",
+      "latency": "Latency",
+      "model": "Model",
+      "responsePreview": "Response Preview",
+      "totalLatency": "Total Latency"
+    },
+    "rawResponse": {
+      "hint": "This shows the raw response content. You can check if the keyword exists in the response here.",
+      "title": "Raw Response Body"
+    },
+    "status": {
+      "green": "Available",
+      "red": "Unavailable",
+      "yellow": "Degraded"
+    },
+    "streamInfo": {
+      "chunksCount": "Chunks Count",
+      "isStreaming": "Streaming",
+      "no": "No",
+      "title": "Stream Response Info",
+      "yes": "Yes"
+    },
+    "timing": {
+      "firstByte": "First Byte",
+      "testedAt": "Tested At",
+      "title": "Timing Info",
+      "totalLatency": "Total Latency"
+    },
+    "tokenUsage": {
+      "cacheCreation": "Cache Creation",
+      "cacheRead": "Cache Read",
+      "input": "Input",
+      "output": "Output",
+      "title": "Token Usage"
+    },
+    "validation": {
+      "content": {
+        "failed": "Target not found",
+        "passed": "Contains target string",
+        "target": "Target",
+        "title": "Tier 3: Content Validation"
+      },
+      "failed": "Failed",
+      "http": {
+        "failed": "4xx/5xx Failed",
+        "passed": "2xx/3xx Success",
+        "statusCode": "Status Code",
+        "title": "Tier 1: HTTP Status"
+      },
+      "latency": {
+        "actual": "Actual Latency",
+        "failed": "Exceeded threshold",
+        "passed": "Within threshold",
+        "title": "Tier 2: Latency Threshold"
+      },
+      "passed": "Passed",
+      "timeout": "Timeout",
+      "title": "Three-tier Validation Details"
+    }
+  },
+  "selectApiFormat": "Select provider type to test",
+  "selectPreset": "Select preset template",
+  "streamFormat": "Stream format",
+  "streamInfo": "Stream response info",
+  "streamResponse": "Stream response",
+  "success": "Success",
+  "successContains": "Success Keyword",
+  "successContainsDesc": "Response must contain this keyword to be considered successful",
+  "successContainsPlaceholder": "pong",
+  "testApi": "Provider Model Test",
+  "testFailed": "Test failed",
+  "testFailedRetry": "Test failed, please retry",
+  "testModel": "Test model",
+  "testModelDesc": "Leave empty to use the default model or type one manually",
+  "testSuccess": "Model test succeeded",
+  "testing": "Testing...",
+  "timeout": {
+    "desc": "Max wait time for test request (5-120 sec)",
+    "geminiHint": ", Gemini Thinking models recommend 60+ sec",
+    "label": "Timeout (seconds)"
+  },
+  "truncatedBrief": "Showing first {length} characters, click \"View Details\" for more",
+  "truncatedPreview": "Showing first {length} characters, copy to see full content",
+  "unknown": "Unknown",
+  "usage": "Token usage",
+  "viewDetails": "View Details"
+}

+ 9 - 0
messages/en/settings/providers/form/buttons.json

@@ -0,0 +1,9 @@
+{
+  "collapseAll": "Collapse All Advanced Settings",
+  "delete": "Delete",
+  "expandAll": "Expand All Advanced Settings",
+  "submit": "Confirm Add",
+  "submitting": "Adding...",
+  "update": "Confirm Update",
+  "updating": "Updating..."
+}

+ 3 - 0
messages/en/settings/providers/form/common.json

@@ -0,0 +1,3 @@
+{
+  "core": "Core"
+}

+ 6 - 0
messages/en/settings/providers/form/deleteDialog.json

@@ -0,0 +1,6 @@
+{
+  "cancel": "Cancel",
+  "confirm": "Confirm Delete",
+  "description": "Are you sure you want to delete provider \"{name}\"? This action cannot be undone.",
+  "title": "Delete Provider"
+}

+ 8 - 0
messages/en/settings/providers/form/errors.json

@@ -0,0 +1,8 @@
+{
+  "addFailed": "Failed to add provider",
+  "deleteFailed": "Failed to delete provider",
+  "groupTagTooLong": "Provider group tags are too long (max {max} chars total)",
+  "invalidUrl": "Please enter a valid API address",
+  "invalidWebsiteUrl": "Please enter a valid provider website URL",
+  "updateFailed": "Failed to update provider"
+}

+ 13 - 0
messages/en/settings/providers/form/failureThresholdConfirmDialog.json

@@ -0,0 +1,13 @@
+{
+  "cancel": "Cancel",
+  "confirm": "Confirm Save",
+  "confirmQuestion": "Are you sure you want to save this configuration?",
+  "descriptionDisabledAction": "disabling the circuit breaker",
+  "descriptionDisabledMiddle": ", which means ",
+  "descriptionDisabledPrefix": "You are setting the circuit breaker failure threshold to ",
+  "descriptionDisabledSuffix": ". The provider will not be circuit-broken due to consecutive failures.",
+  "descriptionDisabledValue": "0",
+  "descriptionHighValuePrefix": "You are setting the circuit breaker failure threshold to ",
+  "descriptionHighValueSuffix": ", which is a high value and may cause the provider to be circuit-broken only after many failures.",
+  "title": "Confirm Special Configuration"
+}

+ 7 - 0
messages/en/settings/providers/form/key.json

@@ -0,0 +1,7 @@
+{
+  "currentKey": "Current key: {key}",
+  "label": "API Key",
+  "leaveEmpty": "(Leave empty to keep unchanged)",
+  "leaveEmptyDesc": "Leave empty to keep existing key",
+  "placeholder": "Enter API Key"
+}

+ 5 - 0
messages/en/settings/providers/form/maxRetryAttempts.json

@@ -0,0 +1,5 @@
+{
+  "desc": "Including the first call, the maximum number of attempts for a single provider before switching. Leave empty to use the system default.",
+  "label": "Max attempts per provider",
+  "placeholder": "2"
+}

+ 14 - 0
messages/en/settings/providers/form/modelRedirect.json

@@ -0,0 +1,14 @@
+{
+  "add": "Add",
+  "addNewRule": "Add New Rule",
+  "alreadyExists": "Model \"{model}\" already has a redirect rule",
+  "currentRules": "Current Rules ({count})",
+  "description": "Redirect Claude Code client requested models (e.g. claude-sonnet-4.5) to upstream provider supported models (e.g. glm-4.6, gemini-pro). For cost optimization or third-party AI integration.",
+  "emptyState": "No redirect rules yet. After adding rules, the system will automatically rewrite model names in requests.",
+  "sourceEmpty": "Source model name cannot be empty",
+  "sourceModel": "User Requested Model",
+  "sourcePlaceholder": "e.g. claude-sonnet-4-5-20250929",
+  "targetEmpty": "Target model name cannot be empty",
+  "targetModel": "Actual Forwarded Model",
+  "targetPlaceholder": "e.g. glm-4.6"
+}

+ 20 - 0
messages/en/settings/providers/form/modelSelect.json

@@ -0,0 +1,20 @@
+{
+  "allowAllModels": "Allow all {type} models",
+  "claude": "Claude",
+  "clear": "Clear",
+  "gemini": "Gemini",
+  "loading": "Loading...",
+  "manualAdd": "Manually Add Model",
+  "manualDesc": "Support adding any model name (not limited to price table)",
+  "manualPlaceholder": "Enter model name (e.g. gpt-5-turbo)",
+  "notFound": "Model not found",
+  "openai": "OpenAI",
+  "refresh": "Refresh model list",
+  "searchPlaceholder": "Search model name...",
+  "selectAll": "Select All ({count})",
+  "selectedCount": "Selected {count} models",
+  "sourceFallback": "Local",
+  "sourceFallbackDesc": "Using local price list (upstream unavailable or unsupported)",
+  "sourceUpstream": "Upstream",
+  "sourceUpstreamDesc": "Model list from upstream provider API"
+}

+ 4 - 0
messages/en/settings/providers/form/name.json

@@ -0,0 +1,4 @@
+{
+  "label": "Provider Name *",
+  "placeholder": "e.g. Zhipu"
+}

+ 10 - 0
messages/en/settings/providers/form/providerTypes.json

@@ -0,0 +1,10 @@
+{
+  "claude": "Claude (Anthropic Messages API)",
+  "claudeAuth": "Claude (Anthropic Auth Token)",
+  "codex": "Codex (Response API)",
+  "gemini": "Gemini (Google Gemini API)",
+  "geminiCli": "Gemini CLI",
+  "geminiCliDisabled": " - in development",
+  "openaiCompatible": "OpenAI Compatible",
+  "openaiCompatibleDisabled": " - in development"
+}

+ 21 - 0
messages/en/settings/providers/form/proxyTest.json

@@ -0,0 +1,21 @@
+{
+  "connectionFailed": "Connection failed",
+  "connectionMethod": "Connection method:",
+  "connectionSuccess": "Connection successful",
+  "direct": "Direct",
+  "errorType": "Error type:",
+  "fillUrlFirst": "Please fill in provider URL first",
+  "networkError": "Network error:",
+  "noResult": "Test succeeded but no result returned",
+  "proxy": "Proxy",
+  "proxyError": "Proxy error:",
+  "responseTime": "Response time:",
+  "statusCode": "Status code:",
+  "testConnection": "Test Connection",
+  "testFailed": "Test failed",
+  "testFailedRetry": "Test failed, please retry",
+  "testing": "Testing...",
+  "timeoutError": "Connection timeout (5s). Please check:\n1. Is proxy server accessible\n2. Are proxy address and port correct\n3. Are proxy credentials correct",
+  "viaDirect": "(direct)",
+  "viaProxy": "(via proxy)"
+}

+ 313 - 0
messages/en/settings/providers/form/sections.json

@@ -0,0 +1,313 @@
+{
+  "apiTest": {
+    "desc": "Validate whether the selected provider type and model respond correctly. Defaults to the routing configuration unless overridden.",
+    "summary": "Verify provider & model connectivity",
+    "testLabel": "Provider Model Test",
+    "title": "Provider Model Test"
+  },
+  "circuitBreaker": {
+    "desc": "Automatically break on consecutive failures to protect overall service quality",
+    "failureThreshold": {
+      "desc": "Number of consecutive failures to trigger break",
+      "label": "Failure Threshold",
+      "placeholder": "5"
+    },
+    "maxRetryAttempts": {
+      "desc": "Total tries (including the first call) before switching providers. Leave empty to use the system default.",
+      "label": "Max Attempts Per Provider",
+      "placeholder": "2"
+    },
+    "openDuration": {
+      "desc": "Time before switching to half-open",
+      "label": "Break Duration (minutes)",
+      "placeholder": "30"
+    },
+    "successThreshold": {
+      "desc": "Number of successes in half-open to fully recover",
+      "label": "Recovery Threshold",
+      "placeholder": "2"
+    },
+    "summary": "{failureThreshold} failures / {openDuration} min break / {successThreshold} successes to recover / {maxRetryAttempts} attempts per provider",
+    "title": "Circuit Breaker"
+  },
+  "codexStrategy": {
+    "desc": "Control how to handle the instructions field in Codex requests; affects gateway compatibility",
+    "hint": "Hint: Some strict Codex gateways (e.g. 88code, foxcode) require official instructions. Choose \"Auto\" or \"Force official\".",
+    "select": {
+      "auto": {
+        "desc": "Pass through client instructions; on 400 error, retry with official prompt",
+        "label": "Auto (recommended)"
+      },
+      "force": {
+        "desc": "Always use official Codex CLI instructions (~4000+ chars)",
+        "label": "Force official"
+      },
+      "keep": {
+        "desc": "Always pass through client instructions, no auto retry (for permissive gateways)",
+        "label": "Pass-through"
+      },
+      "label": "Strategy",
+      "placeholder": "Select a strategy"
+    },
+    "summary": {
+      "auto": "Auto (recommended)",
+      "force": "Force official",
+      "keep": "Pass-through"
+    },
+    "title": "Codex Instructions Policy"
+  },
+  "mcpPassthrough": {
+    "desc": "When enabled, pass through MCP tool calls to specified AI provider (e.g. minimax for image recognition, web search)",
+    "hint": "Hint: MCP passthrough allows Claude Code client to use tool capabilities provided by third-party AI providers (e.g. image recognition, web search)",
+    "select": {
+      "custom": {
+        "desc": "Pass through to custom MCP service (reserved, not implemented yet)",
+        "label": "Custom"
+      },
+      "glm": {
+        "desc": "Pass through to GLM MCP service (supports image analysis, video analysis, etc.)",
+        "label": "GLM"
+      },
+      "label": "Passthrough Type",
+      "minimax": {
+        "desc": "Pass through to minimax MCP service (supports image recognition, web search, etc.)",
+        "label": "Minimax"
+      },
+      "none": {
+        "desc": "Do not enable MCP passthrough (default)",
+        "label": "Disabled"
+      },
+      "placeholder": "Select passthrough type"
+    },
+    "summary": {
+      "custom": "Custom (Reserved)",
+      "glm": "GLM",
+      "minimax": "Minimax",
+      "none": "Disabled"
+    },
+    "title": "MCP Passthrough Configuration",
+    "urlAuto": "Auto-extracted: {url}",
+    "urlDesc": "MCP service base URL. Leave empty to auto-extract from provider URL",
+    "urlLabel": "MCP Passthrough URL",
+    "urlPlaceholder": "https://api.minimaxi.com"
+  },
+  "proxy": {
+    "desc": "Configure a proxy to improve connectivity (HTTP, HTTPS, SOCKS4, SOCKS5 supported)",
+    "fallback": {
+      "desc": "When enabled, will try direct connection if proxy fails",
+      "label": "Fallback to direct on proxy failure"
+    },
+    "summary": {
+      "configured": "Proxy configured",
+      "fallback": " (fallback enabled)",
+      "none": "Not configured"
+    },
+    "test": {
+      "desc": "Test accessing provider URL via proxy (HEAD request, no credits consumed)",
+      "label": "Connectivity Test"
+    },
+    "title": "Proxy",
+    "url": {
+      "formats": "Supported formats:",
+      "label": "Proxy URL",
+      "optional": "(optional)",
+      "placeholder": "e.g. http://proxy.example.com:8080 or socks5://127.0.0.1:1080"
+    }
+  },
+  "rateLimit": {
+    "dailyResetMode": {
+      "desc": {
+        "fixed": "Reset quota at a fixed time each day",
+        "rolling": "Reset 24 hours after first API call"
+      },
+      "label": "Daily Reset Mode",
+      "options": {
+        "fixed": "Fixed Time Reset",
+        "rolling": "Rolling Window (24h)"
+      }
+    },
+    "dailyResetTime": {
+      "label": "Daily Reset Time (HH:mm)"
+    },
+    "limit5h": {
+      "label": "5h Spend Limit (USD)",
+      "placeholder": "Leave empty for unlimited"
+    },
+    "limitConcurrent": {
+      "label": "Concurrent Sessions Limit",
+      "placeholder": "0 means unlimited"
+    },
+    "limitDaily": {
+      "label": "Daily Spend Limit (USD)",
+      "placeholder": "Leave empty for unlimited"
+    },
+    "limitMonthly": {
+      "label": "Monthly Spend Limit (USD)",
+      "placeholder": "Leave empty for unlimited"
+    },
+    "limitTotal": {
+      "label": "Total Spend Limit (USD)",
+      "placeholder": "Leave empty for unlimited"
+    },
+    "limitWeekly": {
+      "label": "Weekly Spend Limit (USD)",
+      "placeholder": "Leave empty for unlimited"
+    },
+    "summary": {
+      "concurrent": "Concurrent: {count}",
+      "daily": "Day: ${amount} (reset ${resetTime})",
+      "fiveHour": "5h: ${amount}",
+      "monthly": "Month: ${amount}",
+      "none": "Unlimited",
+      "total": "Total: ${amount}",
+      "weekly": "Week: ${amount}"
+    },
+    "title": "Rate Limit"
+  },
+  "routing": {
+    "cacheTtl": {
+      "desc": "Force prompt cache TTL; only affects requests with cache_control.",
+      "label": "Cache TTL Override",
+      "options": {
+        "1h": "1 hour",
+        "5m": "5 minutes",
+        "inherit": "No override (follow client)"
+      }
+    },
+    "codexOverrides": {
+      "parallelToolCalls": {
+        "help": "Controls whether parallel tool calls are allowed. \"inherit\" follows the client request. Disabling may reduce tool-call concurrency.",
+        "label": "Parallel Tool Calls Override",
+        "options": {
+          "false": "Force disable",
+          "inherit": "No override (follow client)",
+          "true": "Force enable"
+        }
+      },
+      "reasoningEffort": {
+        "help": "Controls how much reasoning effort the model uses before answering. \"inherit\" follows the client request; other values force override reasoning.effort. Note: \"none\" is only supported on GPT-5.1 models; \"xhigh\" is only supported on GPT-5.1-Codex-Max. Using an unsupported value will cause an upstream error.",
+        "label": "Reasoning Effort Override",
+        "options": {
+          "high": "high",
+          "inherit": "No override (follow client)",
+          "low": "low",
+          "medium": "medium (default)",
+          "minimal": "minimal",
+          "none": "none (GPT-5.1 only)",
+          "xhigh": "xhigh (GPT-5.1-Codex-Max only)"
+        }
+      },
+      "reasoningSummary": {
+        "help": "Controls whether the Responses API returns reasoning summaries. \"auto\" returns a condensed summary, \"detailed\" returns a more comprehensive one. \"inherit\" follows the client request.",
+        "label": "Reasoning Summary Override",
+        "options": {
+          "auto": "auto",
+          "detailed": "detailed",
+          "inherit": "No override (follow client)"
+        }
+      },
+      "textVerbosity": {
+        "help": "Controls how verbose the model output is. \"low\" is concise, \"high\" is verbose. \"inherit\" follows the client request.",
+        "label": "Text Verbosity Override",
+        "options": {
+          "high": "high",
+          "inherit": "No override (follow client)",
+          "low": "low",
+          "medium": "medium (default)"
+        }
+      }
+    },
+    "context1m": {
+      "desc": "Configure 1M context window support. Only affects Sonnet models (claude-sonnet-4-5, claude-sonnet-4). Tiered pricing applies when enabled.",
+      "label": "1M Context Window",
+      "options": {
+        "disabled": "Disabled",
+        "forceEnable": "Force Enable (for supported models)",
+        "inherit": "Inherit (follow client request)"
+      }
+    },
+    "joinClaudePool": {
+      "desc": "When enabled, this provider will participate in load balancing with Claude-type providers",
+      "help": "Available only when there is a redirect mapping to claude-* models. When users request claude-* models, this provider also joins scheduling.",
+      "label": "Join Claude Routing Pool"
+    },
+    "modelRedirects": {
+      "label": "Model Redirects",
+      "optional": "(optional)"
+    },
+    "modelWhitelist": {
+      "allowAll": "✓ Allow all models (recommended)",
+      "desc": "Restrict which models this provider can serve. By default, a provider can serve all models of its type.",
+      "label": "Allowed Models",
+      "moreModels": "+{count} more",
+      "optional": "(optional)",
+      "selectedOnly": "Only the selected {count} models are allowed. Other models will not be routed to this provider.",
+      "title": "Model Allowlist"
+    },
+    "preserveClientIp": {
+      "desc": "Pass x-forwarded-for / x-real-ip to upstream providers (may expose real client IP)",
+      "help": "Keep off by default for privacy. Enable only when upstream must see the end-user IP.",
+      "label": "Forward client IP"
+    },
+    "providerType": {
+      "desc": "(determines scheduling policy)",
+      "label": "Provider Type",
+      "placeholder": "Select provider type"
+    },
+    "providerTypeDesc": "Choose the API format type of the provider.",
+    "providerTypeDisabledNote": "Note: OpenAI Compatible is under development and currently unavailable",
+    "scheduleParams": {
+      "costMultiplier": {
+        "desc": "Cost multiplier. Official provider = 1.0, 20% cheaper = 0.8, 20% more expensive = 1.2 (up to 4 decimals)",
+        "label": "Cost Multiplier",
+        "placeholder": "1.0"
+      },
+      "group": {
+        "desc": "Group tag. Only users whose providerGroup matches can use this provider. Example: set to \"premium\" to serve users with providerGroup=\"premium\" only",
+        "label": "Provider Group",
+        "placeholder": "e.g. premium, economy"
+      },
+      "priority": {
+        "desc": "Lower value = higher priority (0 is highest). The system only chooses from the highest priority tier. Suggested: primary=0, standby=1, emergency=2",
+        "label": "Priority",
+        "placeholder": "0"
+      },
+      "title": "Scheduling",
+      "weight": {
+        "desc": "Weighted random. Within the same priority, higher weight increases selection probability. Example 1:2:3 ≈ 16%:33%:50%",
+        "label": "Weight",
+        "placeholder": "1"
+      }
+    },
+    "summary": {
+      "models": "{count} whitelisted models",
+      "none": "Not configured",
+      "redirects": "{count} redirects"
+    },
+    "title": "Routing"
+  },
+  "timeout": {
+    "desc": "Configure request timeout duration, 0 means disable timeout",
+    "disableHint": "Set to 0 to disable the timeout (for canary rollback scenarios only, not recommended)",
+    "nonStreamingTotal": {
+      "core": "true",
+      "desc": "Non-streaming request total timeout, range 60-1200 seconds, default 600 seconds (10 minutes)",
+      "label": "Non-streaming Total Timeout (seconds)",
+      "placeholder": "600"
+    },
+    "streamingFirstByte": {
+      "core": "true",
+      "desc": "Streaming request first byte timeout, range 1-120 seconds, default 30 seconds",
+      "label": "Streaming First Byte Timeout (seconds)",
+      "placeholder": "30"
+    },
+    "streamingIdle": {
+      "core": "true",
+      "desc": "Streaming request idle timeout, range 60-600 seconds, enter 0 to disable (prevent mid-stream stalling)",
+      "label": "Streaming Idle Timeout (seconds)",
+      "placeholder": "60"
+    },
+    "summary": "First byte: {streaming}s | Stream interval: {idle}s | Non-streaming: {nonStreaming}s",
+    "title": "Timeout Configuration"
+  }
+}

+ 204 - 0
messages/en/settings/providers/form/strings.json

@@ -0,0 +1,204 @@
+{
+  "addRedirect": "Add Redirect",
+  "allowAllModels": "✓ Allow All Models (Recommended)",
+  "apiAddress": "API Address",
+  "apiAddressPlaceholder": "e.g. https://open.bigmodel.cn/api/anthropic",
+  "apiAddressRequired": "API Address *",
+  "apiKey": "API Key",
+  "apiKeyCurrent": "Current key:",
+  "apiKeyLeaveEmpty": "(Leave empty to keep unchanged)",
+  "apiKeyLeaveEmptyDesc": "Leave empty to keep existing key",
+  "apiKeyOptional": "Leave empty to keep existing key",
+  "apiKeyPlaceholder": "Enter API key",
+  "apiKeyRequired": "API Key *",
+  "baseUrl": "Base URL",
+  "baseUrlPlaceholder": "e.g. https://open.bigmodel.cn/api/anthropic",
+  "baseUrlRequired": "Please fill in provider URL first",
+  "circuitBreakerConfig": "Circuit Breaker Configuration",
+  "circuitBreakerConfigSummary": "{failureThreshold} failures / {openDuration} min circuit break / {successThreshold} successes to recover / {maxRetryAttempts} attempts per provider",
+  "circuitBreakerDesc": "Auto circuit break on consecutive failures to avoid overall service quality impact",
+  "clearSearch": "Clear search",
+  "codexInstructions": "Codex Instructions Policy",
+  "codexInstructionsAuto": "Auto (Recommended)",
+  "codexInstructionsDesc": "(determines scheduling policy)",
+  "codexInstructionsForce": "Force Official",
+  "codexInstructionsKeep": "Keep Original",
+  "codexStrategyAutoDesc": "Pass through client instructions, auto retry with official prompt on 400 error",
+  "codexStrategyAutoLabel": "Auto (Recommended)",
+  "codexStrategyConfig": "Codex Instructions Strategy",
+  "codexStrategyConfigAuto": "Auto (Recommended)",
+  "codexStrategyConfigForce": "Force Official",
+  "codexStrategyConfigKeep": "Keep Original",
+  "codexStrategyDesc": "Control how to handle Codex request instructions field, affects upstream gateway compatibility",
+  "codexStrategyForceDesc": "Always use official Codex CLI instructions (~4000+ chars)",
+  "codexStrategyForceLabel": "Force Official",
+  "codexStrategyHint": "Hint: Some strict Codex gateways (e.g. 88code, foxcode) require official instructions. Choose \"Auto\" or \"Force Official\" strategy",
+  "codexStrategyKeepDesc": "Always pass through client instructions, no auto retry (for lenient gateways)",
+  "codexStrategyKeepLabel": "Keep Original",
+  "codexStrategySelect": "Strategy Selection",
+  "collapseAll": "Collapse All Advanced Configuration",
+  "confirmAdd": "Confirm Add",
+  "confirmAddPending": "Adding...",
+  "confirmUpdate": "Confirm Update",
+  "confirmUpdatePending": "Updating...",
+  "costMultiplier": "Cost Multiplier",
+  "costMultiplierDesc": "Cost calculation multiplier. Official=1.0, 20% cheaper=0.8, 20% more expensive=1.2 (up to 4 decimal places)",
+  "costMultiplierLabel": "Cost Multiplier",
+  "costMultiplierPlaceholder": "1.0",
+  "deleteButton": "Delete",
+  "dialogDescription": "Configure provider details and advanced settings.",
+  "enabled": "Enabled",
+  "expandAll": "Expand All Advanced Configuration",
+  "failureThreshold": "Failure Threshold (times)",
+  "failureThresholdDesc": "How many consecutive failures trigger circuit break",
+  "failureThresholdPlaceholder": "5",
+  "filterAllProviders": "All Providers",
+  "filterByType": "Filter by Provider Type",
+  "filterProvider": "Filter by Provider Type",
+  "group": "Group",
+  "groupPlaceholder": "e.g. premium, economy",
+  "joinClaudePool": "Join Claude Scheduling Pool",
+  "joinClaudePoolDesc": "When enabled, this provider will participate in load balancing with Claude type providers",
+  "joinClaudePoolHelp": "Only available when model redirect config contains mappings to claude-* models. When enabled, this provider will also participate in scheduling when users request claude-* models.",
+  "leaveEmpty": "Leave empty for unlimited",
+  "limit0Means": "0 means unlimited",
+  "limit5hLabel": "5-Hour Spending Limit (USD)",
+  "limitAmount5h": "5-Hour Spending Limit (USD)",
+  "limitAmount5hDesc": "e.g. Provider B has $10 limit, $9.8 consumed",
+  "limitAmountMonthly": "Monthly Spending Limit (USD)",
+  "limitAmountWeekly": "Weekly Spending Limit (USD)",
+  "limitConcurrent": "Concurrent Session Limit",
+  "limitConcurrentDesc": "e.g. Provider C has limit of 2, currently 2 active sessions",
+  "limitConcurrentLabel": "Concurrent Session Limit",
+  "limitMonthlyLabel": "Monthly Spending Limit (USD)",
+  "limitPlaceholder0": "0 means unlimited",
+  "limitPlaceholderUnlimited": "Leave empty for unlimited",
+  "limitWeeklyLabel": "Weekly Spending Limit (USD)",
+  "modelRedirects": "Model Redirects",
+  "modelRedirectsAddNew": "Add New Rule",
+  "modelRedirectsCurrentRules": "Current Rules ({count})",
+  "modelRedirectsDesc": "Redirect Claude Code client model requests (e.g. claude-sonnet-4.5) to upstream provider supported models (e.g. glm-4.6, gemini-pro). For cost optimization or third-party AI integration.",
+  "modelRedirectsEmpty": "No redirect rules yet. System will auto-rewrite model names after adding rules.",
+  "modelRedirectsExists": "Model \"{model}\" already has a redirect rule",
+  "modelRedirectsLabel": "Model Redirects Configuration",
+  "modelRedirectsOptional": "(Optional)",
+  "modelRedirectsSourceModel": "User Requested Model",
+  "modelRedirectsSourcePlaceholder": "e.g. claude-sonnet-4-5-20250929",
+  "modelRedirectsSourceRequired": "Source model name cannot be empty",
+  "modelRedirectsTargetModel": "Actual Forwarded Model",
+  "modelRedirectsTargetPlaceholder": "e.g. glm-4.6",
+  "modelRedirectsTargetRequired": "Target model name cannot be empty",
+  "modelWhitelist": "Model Whitelist",
+  "modelWhitelistAllowAll": "Allow all {type} models",
+  "modelWhitelistAllowAllClause": "Allow all Claude models",
+  "modelWhitelistAllowAllOpenAI": "Allow all OpenAI models",
+  "modelWhitelistClear": "Clear",
+  "modelWhitelistDesc": "Limit models this provider can handle. By default, provider can handle all models of its type.",
+  "modelWhitelistLabel": "Allowed Models",
+  "modelWhitelistLoading": "Loading...",
+  "modelWhitelistManualAdd": "Manually Add Model",
+  "modelWhitelistManualDesc": "Support adding any model name (not limited to price table)",
+  "modelWhitelistManualPlaceholder": "Enter model name (e.g. gpt-5-turbo)",
+  "modelWhitelistNotFound": "Model not found",
+  "modelWhitelistSearchPlaceholder": "Search model name...",
+  "modelWhitelistSelectAll": "Select All ({count})",
+  "modelWhitelistSelected": "Selected {count} models",
+  "modelWhitelistSelectedOnly": "Only allow selected {count} models. Requests for other models won't be routed to this provider.",
+  "namePlaceholder": "Enter provider name",
+  "openDuration": "Circuit Break Duration (minutes)",
+  "openDurationDesc": "How long before auto entering half-open state",
+  "openDurationPlaceholder": "30",
+  "priority": "Priority",
+  "priorityDesc": "Lower number = higher priority (0 is highest). System only selects from highest priority providers. Recommendation: Main=0, Backup=1, Emergency=2",
+  "priorityLabel": "Priority",
+  "priorityPlaceholder": "0",
+  "providerGroupDesc": "Provider group tag. Only users with matching providerGroup can use this provider. Example: Set to \"premium\" to allow only providerGroup=\"premium\" users",
+  "providerGroupLabel": "Provider Group",
+  "providerGroupPlaceholder": "e.g. premium, economy",
+  "providerName": "Provider Name",
+  "providerNamePlaceholder": "e.g. Zhipu",
+  "providerNameRequired": "Provider Name *",
+  "providerType": "Provider Type",
+  "providerTypeDesc": "Select the API format type for the provider.",
+  "providerTypeDisabledNote": "Note: Gemini CLI and OpenAI Compatible types are under development",
+  "proxy": "Proxy",
+  "proxyAddressFormats": "Supported formats:",
+  "proxyAddressLabel": "Proxy Address",
+  "proxyAddressOptional": "(Optional)",
+  "proxyAddressPlaceholder": "e.g. http://proxy.example.com:8080 or socks5://127.0.0.1:1080",
+  "proxyConfig": "Proxy Configuration",
+  "proxyConfigDesc": "Configure proxy server to improve provider connectivity (supports HTTP, HTTPS, SOCKS4, SOCKS5)",
+  "proxyConfigNone": "Not configured",
+  "proxyConfigSummary": "Proxy configured",
+  "proxyConfigSummaryFallback": " (fallback enabled)",
+  "proxyConfigured": "Proxy configured",
+  "proxyFallback": "Proxy Fallback",
+  "proxyFallbackDesc": "When enabled, auto try direct connection on proxy failure",
+  "proxyFallbackLabel": "Fallback to direct on proxy failure",
+  "proxyNotConfigured": "Not configured",
+  "proxyTestButton": "Test Connection",
+  "proxyTestDesc": "Test provider URL access via configured proxy (uses HEAD request, no quota consumption)",
+  "proxyTestFailed": "Connection Failed",
+  "proxyTestFillUrl": "Please fill in provider URL first",
+  "proxyTestLabel": "Connection Test",
+  "proxyTestNetworkError": "Network error: {error}",
+  "proxyTestProxyError": "Proxy error: {error}",
+  "proxyTestResponseTime": "Response time: {time}",
+  "proxyTestResultConnectionMethod": "Connection method: {via}",
+  "proxyTestResultConnectionMethodDirect": "Direct",
+  "proxyTestResultConnectionMethodProxy": "Proxy",
+  "proxyTestResultErrorType": "Error type: {type}",
+  "proxyTestResultFailed": "Connection failed",
+  "proxyTestResultMessage": "{message}",
+  "proxyTestResultResponseTime": "Response time: {time}ms",
+  "proxyTestResultStatusCode": "Status code: {code}",
+  "proxyTestResultSuccess": "Connection successful {via}",
+  "proxyTestStatusCode": "| Status code: {code}",
+  "proxyTestSuccess": "Connection Successful",
+  "proxyTestTesting": "Testing...",
+  "proxyTestTimeout": "Connection timeout (5s). Please check:\n1. Is proxy server accessible\n2. Are proxy address and port correct\n3. Are proxy credentials correct",
+  "proxyTestViaDirect": "(direct)",
+  "proxyTestViaProxy": "(via proxy)",
+  "proxyUrl": "Proxy Address",
+  "proxyUrlPlaceholder": "e.g. http://proxy.example.com:8080 or socks5://127.0.0.1:1080",
+  "rateLimitConfig": "Rate Limit Configuration",
+  "rateLimitConfigNone": "Unlimited",
+  "rateLimitConfigSummary": "5h: ${fiveHour}, Weekly: ${weekly}, Monthly: ${monthly}, Concurrent: {concurrent}",
+  "remark": "Remark",
+  "remarkPlaceholder": "Optional: Add notes...",
+  "removeRedirect": "Remove Redirect",
+  "routingConfig": "Routing Configuration",
+  "routingConfigNone": "Not configured",
+  "routingConfigSummary": "{models} model whitelist, {redirects} redirects",
+  "scheduleParams": "Scheduling Parameters",
+  "searchClear": "Clear search",
+  "searchPlaceholder": "Search provider name, URL, remark...",
+  "selectProviderType": "Select provider type",
+  "sort": "Sort Providers",
+  "sortByCost": "By Cost",
+  "sortByCreated": "By Created (New-Old)",
+  "sortByName": "By Name (A-Z)",
+  "sortByPriority": "By Priority (High-Low)",
+  "sortByWeight": "By Weight (High-Low)",
+  "sourceModel": "Source Model Name",
+  "sourceModelPlaceholder": "e.g. claude-sonnet-4-5-20250929",
+  "sourceModelRequired": "Source model name cannot be empty",
+  "successThreshold": "Recovery Threshold (times)",
+  "successThresholdDesc": "How many successes in half-open state to fully recover",
+  "successThresholdPlaceholder": "2",
+  "targetModel": "Target Model Name",
+  "targetModelPlaceholder": "e.g. glm-4.6",
+  "targetModelRequired": "Target model name cannot be empty",
+  "testProxy": "Test Connection",
+  "testProxyFailed": "Failed to test proxy connection",
+  "testProxyFailedError": "Connection test failed:",
+  "testProxySuccess": "Proxy connection successful",
+  "validUrlRequired": "Please enter a valid API address",
+  "websiteUrlDesc": "Provider website URL for quick access",
+  "websiteUrlInvalid": "Please enter a valid provider website URL",
+  "websiteUrlPlaceholder": "https://example.com",
+  "weight": "Weight",
+  "weightDesc": "Weighted random probability. Within same priority, higher weight = higher selection probability. E.g. weights 1:2:3 = probabilities 16%:33%:50%",
+  "weightLabel": "Weight",
+  "weightPlaceholder": "1"
+}

+ 4 - 0
messages/en/settings/providers/form/success.json

@@ -0,0 +1,4 @@
+{
+  "created": "Provider added successfully",
+  "createdDesc": "Provider \"{name}\" has been added"
+}

+ 4 - 0
messages/en/settings/providers/form/title.json

@@ -0,0 +1,4 @@
+{
+  "create": "Add Provider",
+  "edit": "Edit Provider"
+}

+ 4 - 0
messages/en/settings/providers/form/url.json

@@ -0,0 +1,4 @@
+{
+  "label": "API Address *",
+  "placeholder": "e.g. https://open.bigmodel.cn/api/anthropic"
+}

+ 9 - 0
messages/en/settings/providers/form/urlPreview.json

@@ -0,0 +1,9 @@
+{
+  "copy": "Copy",
+  "copyFailed": "Copy failed",
+  "copySuccess": "Copied {name} to clipboard",
+  "duplicatePath": "Duplicate path detected",
+  "invalidUrl": "Invalid URL format",
+  "invalidUrlDesc": "Please enter a valid HTTP/HTTPS address",
+  "title": "URL Concatenation Preview"
+}

+ 5 - 0
messages/en/settings/providers/form/websiteUrl.json

@@ -0,0 +1,5 @@
+{
+  "desc": "Provider official website for quick access",
+  "label": "Provider Website",
+  "placeholder": "https://example.com"
+}

+ 120 - 0
messages/en/settings/providers/guide.json

@@ -0,0 +1,120 @@
+{
+  "after": "After:",
+  "before": "Before:",
+  "bestPracticesConcurrent": "• Concurrent Control: Set session concurrency by provider API limits",
+  "bestPracticesCost": "• Cost Multiplier: Official=1.0, Self-hosted can be 0.8-1.2",
+  "bestPracticesLimit": "• Limit Settings: Set 5h, 7d, 30d limits based on budget",
+  "bestPracticesPriority": "• Priority Settings: Core providers=0, Backup=1-3",
+  "bestPracticesTitle": "Best Practices",
+  "bestPracticesWeight": "• Weight Config: Set weight by capacity (higher capacity = higher weight)",
+  "circuitBreaker": "Circuit Breaker Check",
+  "circuitBreakerOpen": "A filtered, remaining: B, C, D",
+  "circuitBreakerRecovery": "A automatically recovers to half-open after 60 seconds",
+  "circuitBreakerRecovery5h": "Auto recovery after 5-hour sliding window",
+  "costOptimize": "2. Cost Optimization: Within same priority, lower cost multiplier has higher probability",
+  "costSort": "Cost-based Sorting Fallback",
+  "costSortExample": "All providers: A (default), B (premium), C (premium), D (economy)",
+  "costSortProb": "Lower cost C has higher selection probability",
+  "costSortResult": "After sorting: C (0.8x), A (1.0x)",
+  "decision": "Decision:",
+  "group": "User Group Filtering",
+  "groupDesc": "If user has provider group specified, system prioritizes selection from that group",
+  "groupDowngrade": "Log warning and select from global provider pool",
+  "groupExample": "User configured providerGroup = 'premium'",
+  "groupFallback": "If no available providers in user group, fallback to all providers",
+  "groupFiltered": "Select only from A and C, B and D filtered",
+  "groupUnavailable": "All providers in user group 'vip' are disabled or over limit",
+  "health": "Health Filtering (Circuit Breaker + Rate Limit)",
+  "healthCheck": "Check if B is enabled and healthy",
+  "healthCheckAmountLimit": "Check if spending exceeds limits (5h, 7d, 30d)",
+  "healthCheckAmountLimitExample": "Provider B has $10 limit (5h), $9.8 consumed",
+  "healthCheckCircuit": "Provider A failed 5 times, circuit breaker: open",
+  "healthCheckConcurrent": "Check if current active session count exceeds limit",
+  "healthCheckConcurrentExample": "Provider C limit 2, currently 2 active sessions",
+  "healthFilter": "3. Health Filtering: Auto skip circuit-broken or over-limit providers",
+  "healthFiltered": "B filtered (near limit), remaining: C, D",
+  "healthFiltered2": "C filtered (full), remaining: D",
+  "history": "Check Request History",
+  "historyDesc": "Query providers used by this API Key in last 10 seconds",
+  "priority": "Priority Layering",
+  "priorityExample": "4 enabled providers with different priorities",
+  "priorityFirst": "1. Priority First: Select only from highest priority (lowest number) providers",
+  "priorityResult": "Filtered to highest priority (0) providers: A, C",
+  "priorityStep": "System first filters by priority, selecting only from highest priority providers",
+  "randomResult": "Finally selected C randomly",
+  "randomSelect": "Weighted Random",
+  "reset": "Manual Circuit Breaker Reset",
+  "resetSuccess": "Circuit breaker reset",
+  "scenario1Desc": "System first filters by priority, selecting only from highest priority providers",
+  "scenario1Step1": "Initial State",
+  "scenario1Step1After": "Filtered to highest priority (0) providers: A, C",
+  "scenario1Step1Before": "Provider A (priority 0), B (priority 1), C (priority 0), D (priority 2)",
+  "scenario1Step1Decision": "Select only from A and C, B and D filtered out",
+  "scenario1Step1Desc": "4 enabled providers with different priorities",
+  "scenario1Step2": "Cost Sorting",
+  "scenario1Step2After": "After sorting: C (0.8x), A (1.0x)",
+  "scenario1Step2Before": "A (cost 1.0x), C (cost 0.8x)",
+  "scenario1Step2Decision": "Lower cost C has higher selection probability",
+  "scenario1Step2Desc": "Within same priority, sort by cost multiplier low to high",
+  "scenario1Step3": "Weighted Random",
+  "scenario1Step3After": "C has 75% probability, A has 25%",
+  "scenario1Step3Before": "C (weight 3), A (weight 1)",
+  "scenario1Step3Decision": "Finally randomly selected C",
+  "scenario1Step3Desc": "Use weight for random selection, higher weight = higher probability",
+  "scenario1Title": "Priority Layering",
+  "scenario2Desc": "If user has provider group specified, system prioritizes selection from that group",
+  "scenario2Step1": "Check User Group",
+  "scenario2Step1After": "Filtered to 'premium' group: B, C",
+  "scenario2Step1Before": "All providers: A (default), B (premium), C (premium), D (economy)",
+  "scenario2Step1Decision": "Select only from B and C",
+  "scenario2Step1Desc": "User configured providerGroup = 'premium'",
+  "scenario2Step2": "Group Fallback",
+  "scenario2Step2After": "Fallback to all enabled providers: A, B, C, D",
+  "scenario2Step2Before": "All providers in user group 'vip' disabled or over limit",
+  "scenario2Step2Decision": "Log warning and select from global provider pool",
+  "scenario2Step2Desc": "If no available providers in user group, fallback to all providers",
+  "scenario2Title": "User Group Filtering",
+  "scenario3Desc": "System auto filters circuit-broken or over-limit providers",
+  "scenario3Step1": "Circuit Breaker Check",
+  "scenario3Step1After": "A filtered, remaining: B, C, D",
+  "scenario3Step1Before": "Provider A failed 5 times, circuit breaker: open",
+  "scenario3Step1Decision": "A auto recovers to half-open after 60s",
+  "scenario3Step1Desc": "Circuit breaker opens after 5 consecutive failures, unavailable for 60s",
+  "scenario3Step2": "Amount Rate Limit",
+  "scenario3Step2After": "B filtered (near limit), remaining: C, D",
+  "scenario3Step2Before": "Provider B 5h limit $10, consumed $9.8",
+  "scenario3Step2Decision": "Auto recovery after 5h sliding window",
+  "scenario3Step2Desc": "Check if spending exceeds limits (5h, 7d, 30d)",
+  "scenario3Step3": "Concurrent Session Limit",
+  "scenario3Step3After": "C filtered (full), remaining: D",
+  "scenario3Step3Before": "Provider C concurrent limit 2, currently 2 active sessions",
+  "scenario3Step3Decision": "Auto release after session expiry (5 min)",
+  "scenario3Step3Desc": "Check if active session count exceeds configured concurrent limit",
+  "scenario3Title": "Health Filtering (Circuit Breaker + Rate Limit)",
+  "scenario4Desc": "Consecutive chats prioritize using same provider, leveraging Claude context cache",
+  "scenario4Step1": "Check Request History",
+  "scenario4Step1After": "Check if B is enabled and healthy",
+  "scenario4Step1Before": "Last request used provider B",
+  "scenario4Step1Decision": "B available, reuse directly, skip random selection",
+  "scenario4Step1Desc": "Query providers used by this API Key in last 10 seconds",
+  "scenario4Step2": "Reuse Invalidation",
+  "scenario4Step2After": "Enter normal selection flow",
+  "scenario4Step2Before": "Last used provider B disabled or circuit-broken",
+  "scenario4Step2Decision": "Select from other available providers",
+  "scenario4Step2Desc": "If last used provider unavailable, reselect",
+  "scenario4Title": "Session Reuse Mechanism",
+  "scenariosTitle": "Interactive Scenario Demos",
+  "session": "Session Reuse Mechanism",
+  "sessionDesc": "If the last used provider is unavailable, reselect",
+  "sessionExample": "Last request used provider B",
+  "sessionExpired": "Session automatically released after expiration (5 minutes)",
+  "sessionFallback": "Select from other available providers",
+  "sessionLastUsed": "B is available, reuse directly, skip random selection",
+  "sessionReuse": "4. Session Reuse: Consecutive chats reuse same provider, saving context costs",
+  "sessionUnavailable": "Last used provider B is disabled or circuit-broken",
+  "step": "Step",
+  "title": "Core Principles",
+  "weight": "Weighted random selection based on weight",
+  "weightCalc": "C has 75% selection probability, A has 25%",
+  "weightExample": "C (weight 3), A (weight 1)"
+}

+ 12 - 0
messages/en/settings/providers/inlineEdit.json

@@ -0,0 +1,12 @@
+{
+  "cancel": "Cancel",
+  "costMultiplierInvalid": "Please enter a non-negative number",
+  "costMultiplierLabel": "Cost Multiplier",
+  "priorityInvalid": "Please enter an integer >= 0",
+  "priorityLabel": "Priority",
+  "save": "Save",
+  "saveFailed": "Save failed",
+  "saveSuccess": "Saved successfully",
+  "weightInvalid": "Please enter an integer between 1 and 100",
+  "weightLabel": "Weight"
+}

+ 37 - 0
messages/en/settings/providers/list.json

@@ -0,0 +1,37 @@
+{
+  "cancelButton": "Cancel",
+  "circuitBroken": "Circuit Broken",
+  "clipboardUnavailable": "Clipboard access is blocked in this environment. Select and copy the key manually.",
+  "confirmDeleteMessage": "Are you sure you want to delete provider \"{name}\"? This action cannot be undone.",
+  "confirmDeleteTitle": "Confirm Delete Provider?",
+  "copyFailed": "Copy failed",
+  "costMultiplier": "Cost Multiplier",
+  "deleteButton": "Delete",
+  "deleteError": "An error occurred during operation",
+  "deleteFailed": "Delete failed",
+  "deleteSuccess": "Deleted successfully",
+  "deleteSuccessDesc": "Provider \"{name}\" has been deleted",
+  "getKeyFailed": "Failed to get key",
+  "keyCopied": "Key copied to clipboard",
+  "keyLoading": "Loading...",
+  "officialWebsite": "Official",
+  "priority": "Priority",
+  "resetCircuitFailed": "Failed to reset circuit breaker",
+  "resetCircuitSuccess": "Circuit breaker reset",
+  "resetCircuitSuccessDesc": "Provider \"{name}\" circuit breaker status cleared",
+  "resetUsageFailed": "Failed to reset total usage",
+  "resetUsageSuccess": "Total usage reset",
+  "resetUsageSuccessDesc": "Provider \"{name}\" total usage has been reset",
+  "resetUsageTitle": "Reset total usage",
+  "statusDisabled": "disabled",
+  "statusEnabled": "enabled",
+  "todayUsageCount": "{count} times",
+  "todayUsageLabel": "Today's Usage",
+  "toggleFailed": "Toggle failed",
+  "toggleSuccess": "Provider {status}",
+  "toggleSuccessDesc": "Provider \"{name}\" status updated",
+  "unknownError": "Unknown error",
+  "viewFullKey": "View Complete API Key",
+  "viewFullKeyDesc": "Please keep it safe and don't share it with others",
+  "weight": "Weight"
+}

+ 9 - 0
messages/en/settings/providers/schedulingDialog.json

@@ -0,0 +1,9 @@
+{
+  "after": "After:",
+  "before": "Before:",
+  "decision": "Decision:",
+  "description": "Understand how the system intelligently selects upstream providers for high availability and cost optimization",
+  "step": "Step",
+  "title": "Provider Scheduling Rules",
+  "triggerButton": "Rules"
+}

+ 7 - 0
messages/en/settings/providers/search.json

@@ -0,0 +1,7 @@
+{
+  "clear": "Clear search",
+  "found": "Found {count} matching provider(s)",
+  "notFound": "No matching providers found",
+  "placeholder": "Search provider name, URL, notes...",
+  "showing": "Showing {filtered} / {total} providers"
+}

+ 5 - 0
messages/en/settings/providers/section.json

@@ -0,0 +1,5 @@
+{
+  "description": "Configure upstream provider rate limiting and concurrent session limits. Leave empty for unlimited.",
+  "leaderboard": "Leaderboard",
+  "title": "Provider Management"
+}

+ 8 - 0
messages/en/settings/providers/sort.json

@@ -0,0 +1,8 @@
+{
+  "byActualPriority": "By Actual Selection Priority",
+  "byCreatedAt": "By Created Time (New-Old)",
+  "byName": "By Name (A-Z)",
+  "byPriority": "By Priority (High-Low)",
+  "byWeight": "By Weight (High-Low)",
+  "placeholder": "Sort Providers"
+}

+ 47 - 0
messages/en/settings/providers/strings.json

@@ -0,0 +1,47 @@
+{
+  "add": "Add Provider",
+  "addFailed": "Failed to add provider",
+  "addProvider": "Add Provider",
+  "addSuccess": "Provider added successfully",
+  "circuitBroken": "Circuit Broken",
+  "clone": "Clone Provider",
+  "cloneFailed": "Copy failed",
+  "confirmDelete": "Are you sure you want to delete this provider?",
+  "confirmDeleteDesc": "Are you sure you want to delete provider \"{name}\"? This action cannot be undone.",
+  "confirmDeleteProvider": "Confirm Delete Provider?",
+  "confirmDeleteProviderDesc": "Are you sure you want to delete provider \"{name}\"? This action is irreversible.",
+  "createProvider": "Add Provider",
+  "delete": "Delete Provider",
+  "deleteFailed": "Failed to delete provider",
+  "deleteSuccess": "Deleted successfully",
+  "description": "Configure API service providers and maintain availability status.",
+  "disabledStatus": "disabled",
+  "displayCount": "Showing {filtered} / {total} providers",
+  "edit": "Edit Provider",
+  "editFailed": "Failed to update provider",
+  "editProvider": "Edit Provider",
+  "enabledStatus": "enabled",
+  "keyLoading": "Loading...",
+  "noProviders": "No providers configured",
+  "noProvidersDesc": "Add your first API provider",
+  "notFound": "No matching providers found",
+  "official": "Official",
+  "resetCircuit": "Circuit breaker reset",
+  "resetCircuitDesc": "Provider \"{name}\" circuit breaker status cleared",
+  "resetCircuitFailed": "Failed to reset circuit breaker",
+  "scheduling": "Scheduling Strategy Details",
+  "schedulingDesc": "Understand how provider selection works with priority layering, session reuse, load balancing and failover",
+  "searchNoResults": "No matching providers found",
+  "searchResults": "Found {count} matching providers",
+  "subtitle": "Provider Management",
+  "subtitleDesc": "Configure upstream provider rate limiting and concurrent session limits. Leave empty for unlimited.",
+  "title": "Provider Management",
+  "todayUsage": "Today's Usage",
+  "todayUsageCount": "{count} times",
+  "toggleFailed": "Toggle failed",
+  "toggleSuccess": "Provider {status}",
+  "toggleSuccessDesc": "Provider \"{name}\" status updated",
+  "updateFailed": "Failed to update provider",
+  "viewKey": "View Complete API Key",
+  "viewKeyDesc": "Please keep it safe and don't share it with others"
+}

+ 26 - 0
messages/en/settings/providers/types.json

@@ -0,0 +1,26 @@
+{
+  "claude": {
+    "description": "Anthropic Official API",
+    "label": "Claude"
+  },
+  "claudeAuth": {
+    "description": "Claude Relay Service",
+    "label": "Claude Auth"
+  },
+  "codex": {
+    "description": "Codex CLI API",
+    "label": "Codex"
+  },
+  "gemini": {
+    "description": "Google Gemini API",
+    "label": "Gemini"
+  },
+  "geminiCli": {
+    "description": "Gemini CLI API",
+    "label": "Gemini CLI"
+  },
+  "openaiCompatible": {
+    "description": "OpenAI Compatible API",
+    "label": "OpenAI Compatible"
+  }
+}

+ 84 - 0
messages/en/settings/requestFilters.json

@@ -0,0 +1,84 @@
+{
+  "actionLabel": {
+    "json_path": "JSON Path Replace",
+    "remove": "Remove Header",
+    "set": "Set Header",
+    "text_replace": "Text Replace"
+  },
+  "add": "Add Filter",
+  "addFailed": "Failed to create filter",
+  "addSuccess": "Filter created",
+  "applyToAll": "Applied to all requests",
+  "confirmDelete": "Delete filter \"{name}\"?",
+  "delete": "Delete Filter",
+  "deleteFailed": "Delete failed",
+  "deleteSuccess": "Filter deleted",
+  "description": "Configure header removal/override and body replacement rules to sanitize requests before forwarding upstream.",
+  "dialog": {
+    "action": "Action",
+    "bindingGlobal": "All Providers (Global)",
+    "bindingGroups": "Provider Groups",
+    "bindingProviders": "Specific Providers",
+    "bindingType": "Apply To",
+    "clear": "Clear",
+    "createTitle": "Add Filter",
+    "description": "Description (optional)",
+    "editTitle": "Edit Filter",
+    "groupsSelected": "{count} group(s) selected",
+    "jsonPathPlaceholder": "e.g. messages.0.content or data.items[0].token",
+    "loading": "Loading...",
+    "matchType": "Match Type",
+    "matchTypeContains": "Contains",
+    "matchTypeExact": "Exact",
+    "matchTypeRegex": "Regex",
+    "name": "Name",
+    "noGroupsFound": "No groups found",
+    "noProvidersFound": "No providers found",
+    "priority": "Priority",
+    "providersSelected": "{count} provider(s) selected",
+    "replacement": "Replacement (optional)",
+    "replacementPlaceholder": "String or JSON, leave blank to clear",
+    "save": "Save",
+    "saving": "Saving...",
+    "scope": "Scope",
+    "searchGroups": "Search groups...",
+    "searchProviders": "Search providers...",
+    "selectAll": "Select All",
+    "selectGroups": "Select groups...",
+    "selectProviders": "Select providers...",
+    "target": "Target field/path",
+    "targetPlaceholder": "Header name or text/path",
+    "validation": {
+      "fieldRequired": "Name and target are required"
+    }
+  },
+  "disable": "Disabled",
+  "edit": "Edit Filter",
+  "editFailed": "Failed to update filter",
+  "editSuccess": "Filter updated",
+  "empty": "No filters yet. Click Add Filter to configure.",
+  "enable": "Enabled",
+  "groups": "Groups",
+  "nav": "Request Filters",
+  "providers": "Providers",
+  "refreshCache": "Refresh Cache",
+  "refreshFailed": "Refresh failed",
+  "refreshSuccess": "Cache refreshed, loaded {count} filters",
+  "scopeLabel": {
+    "body": "Body",
+    "header": "Header"
+  },
+  "table": {
+    "action": "Action",
+    "actions": "Actions",
+    "apply": "Apply",
+    "createdAt": "Created At",
+    "name": "Name",
+    "priority": "Priority",
+    "replacement": "Replacement",
+    "scope": "Scope",
+    "status": "Status",
+    "target": "Target"
+  },
+  "title": "Request Filters"
+}

+ 55 - 0
messages/en/settings/sensitiveWords.json

@@ -0,0 +1,55 @@
+{
+  "add": "Add Sensitive Word",
+  "addFailed": "Failed to create sensitive word",
+  "addSuccess": "Sensitive word created successfully",
+  "cacheStats": "Cache stats: Contains({containsCount}) Exact({exactCount}) Regex({regexCount})",
+  "confirmDelete": "Are you sure you want to delete the sensitive word \"{word}\"?",
+  "delete": "Delete Sensitive Word",
+  "deleteFailed": "Delete failed",
+  "deleteSuccess": "Sensitive word deleted successfully",
+  "description": "Configure sensitive word filtering rules to block requests with sensitive content.",
+  "dialog": {
+    "addDescription": "Configure sensitive word filtering rules. Matched requests will not be forwarded upstream.",
+    "addTitle": "Add Sensitive Word",
+    "creating": "Creating...",
+    "descriptionLabel": "Description",
+    "descriptionPlaceholder": "Optional: Add description...",
+    "editDescription": "Modify sensitive word configuration. Changes will automatically refresh the cache.",
+    "editTitle": "Edit Sensitive Word",
+    "matchTypeContains": "Contains Match - Block if text contains this word",
+    "matchTypeExact": "Exact Match - Block only if exact match",
+    "matchTypeLabel": "Match Type *",
+    "matchTypeRegex": "Regular Expression - Support complex pattern matching",
+    "saving": "Saving...",
+    "wordLabel": "Sensitive Word *",
+    "wordPlaceholder": "Enter sensitive word...",
+    "wordRequired": "Please enter a sensitive word"
+  },
+  "disable": "Sensitive word disabled",
+  "edit": "Edit Sensitive Word",
+  "editFailed": "Failed to update sensitive word",
+  "editSuccess": "Sensitive word updated successfully",
+  "emptyState": "No sensitive words yet. Click 'Add Sensitive Word' in the top right to start configuration.",
+  "enable": "Sensitive word enabled",
+  "refreshCache": "Refresh Cache",
+  "refreshCacheFailed": "Failed to refresh cache",
+  "refreshCacheSuccess": "Cache refreshed successfully, loaded {count} sensitive words",
+  "section": {
+    "description": "Requests blocked by sensitive words will not be forwarded upstream and will not be charged. Supports contains matching, exact matching, and regex patterns.",
+    "title": "Sensitive Words List"
+  },
+  "table": {
+    "actions": "Actions",
+    "createdAt": "Created At",
+    "description": "Description",
+    "matchType": "Match Type",
+    "matchTypeContains": "Contains Match",
+    "matchTypeExact": "Exact Match",
+    "matchTypeRegex": "Regular Expression",
+    "status": "Status",
+    "word": "Sensitive Word"
+  },
+  "title": "Sensitive Words Management",
+  "toggleFailed": "Toggle failed",
+  "toggleFailedError": "Toggle failed:"
+}

+ 22 - 0
messages/en/settings/strings.json

@@ -0,0 +1,22 @@
+{
+  "mcpPassthroughConfig": "MCP Passthrough Configuration",
+  "mcpPassthroughConfigCustom": "Custom (Reserved)",
+  "mcpPassthroughConfigGlm": "GLM",
+  "mcpPassthroughConfigMinimax": "Minimax",
+  "mcpPassthroughConfigNone": "Disabled",
+  "mcpPassthroughCustomDesc": "Pass through to custom MCP service (reserved, not implemented yet)",
+  "mcpPassthroughCustomLabel": "Custom",
+  "mcpPassthroughDesc": "When enabled, pass through MCP tool calls to specified AI provider (e.g. minimax for image recognition, web search)",
+  "mcpPassthroughGlmDesc": "Pass through to GLM MCP service (supports image analysis, video analysis, etc.)",
+  "mcpPassthroughGlmLabel": "GLM",
+  "mcpPassthroughHint": "Hint: MCP passthrough allows Claude Code client to use tool capabilities provided by third-party AI providers (e.g. image recognition, web search)",
+  "mcpPassthroughMinimaxDesc": "Pass through to minimax MCP service (supports image recognition, web search, etc.)",
+  "mcpPassthroughMinimaxLabel": "Minimax",
+  "mcpPassthroughNoneDesc": "Do not enable MCP passthrough (default)",
+  "mcpPassthroughNoneLabel": "Disabled",
+  "mcpPassthroughSelect": "Passthrough Type",
+  "mcpPassthroughUrlAuto": "Auto-extracted: {url}",
+  "mcpPassthroughUrlDesc": "MCP service base URL. Leave empty to auto-extract from provider URL",
+  "mcpPassthroughUrlLabel": "MCP Passthrough URL",
+  "mcpPassthroughUrlPlaceholder": "https://api.minimaxi.com"
+}

+ 52 - 52
messages/ja/dashboard.json

@@ -81,7 +81,7 @@
       "apiKey": "API キー",
       "statusCode": "ステータスコード",
       "minRetryCount": "リトライ回数≥",
-      "minRetryCountPlaceholder": "回数を入力(0 で制限なし)",
+      "minRetryCountPlaceholder": "回数を入力(0 で制限なし)",
       "apply": "フィルターを適用",
       "reset": "リセット",
       "last7days": "7日",
@@ -165,7 +165,7 @@
       "skipped": {
         "title": "スキップ情報",
         "reason": "理由",
-        "warmup": "Warmup 即時応答(CCH)",
+        "warmup": "Warmup 即時応答(CCH)",
         "desc": "このリクエストは Warmup プローブとして識別され、CCH が上流プロバイダーへ転送せずに直接応答しました。課金/レート制限/統計には含まれません。"
       },
       "blocked": {
@@ -189,12 +189,12 @@
         "requestModel": "リクエストモデル",
         "actualModel": "実際の呼び出し",
         "billing": "課金説明",
-        "billingDescription": "システムはリクエストモデル({original})の価格を優先して課金します。価格表にそのモデルが存在しない場合、実際の呼び出しモデル({current})の価格を使用します。",
+        "billingDescription": "システムはリクエストモデル({original})の価格を優先して課金します。価格表にそのモデルが存在しない場合、実際の呼び出しモデル({current})の価格を使用します。",
         "billingModel": "課金モデル",
         "actualModelTooltip": "実際のモデル: {model}",
         "originalModelTooltip": "元のモデル: {model}",
-        "billingDescription_original": "現在の課金モード:リダイレクト前の元のモデル({original})で課金",
-        "billingDescription_redirected": "現在の課金モード:リダイレクト後の実際のモデル({current})で課金",
+        "billingDescription_original": "現在の課金モード:リダイレクト前の元のモデル({original})で課金",
+        "billingDescription_redirected": "現在の課金モード:リダイレクト後の実際のモデル({current})で課金",
         "billingOriginal": "課金: 元",
         "billingRedirected": "課金: 実際"
       },
@@ -232,8 +232,8 @@
       "targetModel": "ターゲットモデル"
     },
     "statusCodes": {
-      "not200": "非 200(エラー/ブロック)",
-      "200": "200 (成功)",
+      "not200": "非 200(エラー/ブロック)",
+      "200": "200(成功)",
       "400": "400 (不正なリクエスト)",
       "401": "401 (未認証)",
       "429": "429 (レート制限)",
@@ -270,7 +270,7 @@
       "providerRanking": "プロバイダーランキング",
       "providerCacheHitRateRanking": "プロバイダーキャッシュ命中率",
       "modelRanking": "モデルランキング",
-      "dailyRanking": "日",
+      "dailyRanking": "日",
       "weeklyRanking": "今週",
       "monthlyRanking": "今月",
       "allTimeRanking": "全期間"
@@ -295,13 +295,13 @@
       "provider": "プロバイダー",
       "model": "モデル",
       "cost": "コスト",
-      "cacheHitRequests": "キャッシュ対象リクエスト数(命中率計算対象)",
+      "cacheHitRequests": "キャッシュ対象リクエスト数(命中率計算対象)",
       "cacheHitRate": "キャッシュ命中率",
       "cacheReadTokens": "キャッシュ読取トークン数",
       "totalTokens": "総トークン数",
       "cacheCreationConsumedAmount": "キャッシュ作成消費額",
       "totalConsumedAmount": "総消費額",
-      "successRate": "成功率",
+      "successRate": "成功率(%)",
       "avgResponseTime": "平均応答時間",
       "avgTtfbMs": "平均TTFB",
       "avgTokensPerSecond": "平均トークン/秒"
@@ -377,7 +377,7 @@
       "totalInput": "総入力",
       "totalOutput": "総出力",
       "cacheCreation": "キャッシュ作成",
-      "cacheTtlMixed": "混",
+      "cacheTtlMixed": "混",
       "cacheRead": "キャッシュ読み取り",
       "total": "合計",
       "totalFee": "総費用",
@@ -474,8 +474,8 @@
       "unknownError": "不明なエラー",
       "prev": "前へ",
       "next": "次へ",
-      "orderAsc": "昇順に切り替え(古い順)",
-      "orderDesc": "降順に切り替え(新しい順)"
+      "orderAsc": "昇順に切り替え(古い順)",
+      "orderDesc": "降順に切り替え(新しい順)"
     },
     "back": "戻る",
     "loadingError": "読み込み失敗"
@@ -589,7 +589,7 @@
       "todayCalls": "今日の呼び出し",
       "todayCost": "今日の消費",
       "lastUsed": "最終使用",
-      "actions": "操作"
+      "actions": "アクション"
     },
     "detailsButton": "詳細情報",
     "modelStats": "モデル統計",
@@ -605,7 +605,7 @@
     "copyFailed": "コピーに失敗しました:",
     "timesUnit": "回",
     "provider": "プロバイダー",
-    "neverUsed": "未使用",
+    "neverUsed": "未使用(未利用)",
     "viewLogsTooltip": "詳細なログを表示",
     "logsButton": "ログ",
     "emptyState": {
@@ -631,7 +631,7 @@
       "renew90d": "90日間更新",
       "renew1y": "1年間更新",
       "renewCustom": "カスタム...",
-      "customPrompt": "新しい有効期限を入力してください(YYYY-MM-DD)。キャンセルするには空のままにしてください。",
+      "customPrompt": "新しい有効期限を入力してください(YYYY-MM-DD)。キャンセルするには空のままにしてください。",
       "invalidDate": "有効な日付を入力してください",
       "enable": "有効化",
       "disable": "無効化",
@@ -758,15 +758,15 @@
     "providerGroup": {
       "label": "プロバイダーグループ",
       "placeholder": "プロバイダーグループタグを入力し、Enterで追加",
-      "description": "このキーのプロバイダーグループ(既定: default)",
+      "description": "このキーのプロバイダーグループ(既定: default)",
       "defaultDescription": "default は groupTag 未設定のプロバイダーを含みます",
-      "descriptionWithUserGroup": "このキーのプロバイダーグループ(ユーザーのグループ: {group}、既定: default)"
+      "descriptionWithUserGroup": "このキーのプロバイダーグループ(ユーザーのグループ: {group}、既定: default)"
     },
     "successTitle": "キーが正常に作成されました",
     "successDescription": "APIキーが正常に作成されました。",
     "generatedKey": {
       "label": "生成されたキー",
-      "hint": "このキーはキー一覧で管理できます(有効/無効、上限設定など)。ただし完全なキーは一度しか表示されません。今すぐコピーして安全に保管してください。"
+      "hint": "このキーはキー一覧で管理できます(有効/無効、上限設定など)。ただし完全なキーは一度しか表示されません。今すぐコピーして安全に保管してください。"
     },
     "errors": {
       "userIdMissing": "ユーザーIDが存在しません",
@@ -789,7 +789,7 @@
     },
     "loadingText": {
       "add": "作成中...",
-      "edit": "保存..."
+      "edit": "保存しています..."
     },
     "username": {
       "label": "ユーザー名",
@@ -797,18 +797,18 @@
     },
     "note": {
       "label": "備考",
-      "placeholder": "備考を入力してください(オプション)",
+      "placeholder": "備考を入力してください(オプション)",
       "description": "ユーザーの用途や備考情報を説明するために使用されます"
     },
     "providerGroup": {
       "label": "プロバイダーグループ",
       "placeholder": "例: default または premium,economy",
-      "description": "ユーザーのプロバイダーグループ(既定: default)。groupTag が未設定のプロバイダーは default に属します。"
+      "description": "ユーザーのプロバイダーグループ(既定: default)。groupTag が未設定のプロバイダーは default に属します。"
     },
     "tags": {
       "label": "ユーザータグ",
-      "placeholder": "タグを入力(Enterで追加)",
-      "description": "分類とフィルタリングのためにタグを追加します(最大20個、各32文字まで)"
+      "placeholder": "タグを入力(Enterで追加)",
+      "description": "分類とフィルタリングのためにタグを追加します(最大20個、各32文字まで)"
     },
     "rpm": {
       "label": "RPM制限",
@@ -854,12 +854,12 @@
       "label": "許可されたクライアント",
       "description": "このアカウントを使用できるCLI/IDEクライアントを制限します。空の場合は制限なし。",
       "customLabel": "カスタムクライアントパターン",
-      "customPlaceholder": "カスタムパターンを入力(例:'xcode', 'my-ide')"
+      "customPlaceholder": "カスタムパターンを入力(例:'xcode', 'my-ide')"
     },
     "allowedModels": {
       "label": "許可モデル",
-      "placeholder": "モデル名を入力(Enterで追加)",
-      "description": "ユーザーを特定のAIモデルに制限します。空白の場合は制限なし(最大50モデル、各64文字)"
+      "placeholder": "モデル名を入力(Enterで追加)",
+      "description": "ユーザーを特定のAIモデルに制限します。空白の場合は制限なし(最大50モデル、各64文字)"
     }
   },
   "deleteKeyConfirm": {
@@ -890,7 +890,7 @@
     "description": "プロバイダーの可用性とパフォーマンス指標をリアルタイムで監視",
     "nav": "可用性モニター",
     "status": {
-      "green": "正常",
+      "green": "正常(OK)",
       "red": "異常",
       "unknown": "不明"
     },
@@ -902,7 +902,7 @@
     "metrics": {
       "systemAvailability": "システム可用性",
       "totalRequests": "総リクエスト数",
-      "successRate": "成功率",
+      "successRate": "成功率(%)",
       "avgLatency": "平均遅延",
       "p50Latency": "P50 遅延",
       "p95Latency": "P95 遅延",
@@ -926,7 +926,7 @@
     },
     "sort": {
       "label": "並び替え",
-      "availability": "可用性",
+      "availability": "可用性(稼働率)",
       "name": "名前",
       "requests": "リクエスト数"
     },
@@ -934,12 +934,12 @@
       "provider": "プロバイダー",
       "type": "タイプ",
       "status": "ステータス",
-      "availability": "可用性",
+      "availability": "可用性(稼働率)",
       "requests": "リクエスト",
-      "successRate": "成功率",
+      "successRate": "成功率(%)",
       "avgLatency": "平均遅延",
       "lastRequest": "最終リクエスト",
-      "actions": "操作"
+      "actions": "アクション"
     },
     "chart": {
       "title": "可用性トレンド",
@@ -973,8 +973,8 @@
     },
     "legend": {
       "green": "優秀 (可用性 95%+)",
-      "lime": "良好 (可用性 80-95%)",
-      "orange": "警告 (可用性 50-80%)",
+      "lime": "良好(可用性 80-95%)",
+      "orange": "警告(可用性 50-80%)",
       "red": "異常 (可用性 <50%)",
       "noData": "データなし"
     },
@@ -1003,7 +1003,7 @@
     "loading": "読み込み中...",
     "error": "読み込み失敗",
     "totalEvents": "総イベント数",
-    "avgUsage": "平均使用率",
+    "avgUsage": "平均用率",
     "affectedUsers": "影響を受けたユーザー数",
     "noData": "データなし",
     "noDataHint": "選択した時間範囲にはレート制限イベントがありません",
@@ -1118,7 +1118,7 @@
         "todayUsage": "本日の使用量",
         "todayCost": "本日の消費",
         "lastUsed": "最終使用",
-        "actions": "操作",
+        "actions": "アクション",
         "quotaButton": "クォータ使用状況を表示",
         "fields": {
           "callsLabel": "呼び出し",
@@ -1182,7 +1182,7 @@
         "7days": "7 日",
         "30days": "30 日",
         "90days": "90 日",
-        "1year": "1 年"
+        "1year": "1年"
       },
       "customDate": "カスタム日付",
       "enableOnRenew": "同時にユーザーを有効化",
@@ -1208,7 +1208,7 @@
       "userEnabled": "ユーザーが有効化されました",
       "deleteFailed": "ユーザーの削除に失敗しました",
       "userDeleted": "ユーザーが削除されました",
-      "saving": "保存..."
+      "saving": "保存しています..."
     },
     "batchEdit": {
       "enterMode": "一括編集",
@@ -1232,7 +1232,7 @@
         "keyFields": "キーフィールド",
         "goBack": "戻って修正",
         "update": "更新を確定",
-        "updating": "更新..."
+        "updating": "更新しています..."
       },
       "toast": {
         "usersUpdated": "{count} ユーザーを更新しました",
@@ -1292,12 +1292,12 @@
       "description": "新規ユーザーを作成し、APIキーを設定",
       "saveFailed": "ユーザーの作成に失敗しました",
       "keyCreateFailed": "キーの作成に失敗しました",
-      "rollbackFailed": "ロールバックに失敗しました。ユーザーのみが作成され、キーが作成されていない可能性があります。手動でユーザーを削除してください(userId: {userId})。",
+      "rollbackFailed": "ロールバックに失敗しました。ユーザーのみが作成され、キーが作成されていない可能性があります。手動でユーザーを削除してください(userId: {userId})。",
       "createSuccess": "ユーザーが作成されました",
       "successTitle": "作成完了",
       "successDescription": "ユーザーとキーが作成されました",
       "generatedKey": "生成されたキー",
-      "keyHint": "このキーはユーザー管理ページで管理できます(有効/無効、上限設定など)。ただし完全なキーは一度しか表示されません。今すぐコピーして安全に保管してください。",
+      "keyHint": "このキーはユーザー管理ページで管理できます(有効/無効、上限設定など)。ただし完全なキーは一度しか表示されません。今すぐコピーして安全に保管してください。",
       "keysSection": "キー",
       "addKey": "キーを追加",
       "removeKey": "キーを削除",
@@ -1320,7 +1320,7 @@
       },
       "dailyMode": {
         "fixed": "固定時刻でリセット",
-        "rolling": "ローリングウィンドウ(24時間)"
+        "rolling": "ローリングウィンドウ(24時間)"
       },
       "quickValues": {
         "unlimited": "無制限",
@@ -1346,7 +1346,7 @@
     "providerGroup": {
       "label": "プロバイダーグループ",
       "placeholder": "プロバイダーグループを選択",
-      "noRestriction": "制限なし(すべてのプロバイダー)",
+      "noRestriction": "制限なし(すべてのプロバイダー)",
       "providerCount": "{count} 件のプロバイダー"
     },
     "dangerZone": {
@@ -1398,7 +1398,7 @@
       },
       "cacheTtlOverride": {
         "label": "Cache TTL の上書き",
-        "inherit": "上書きしない(プロバイダー/クライアントに従う)",
+        "inherit": "上書きしない(プロバイダー/クライアントに従う)",
         "5m": "5分",
         "1h": "1時間"
       }
@@ -1416,7 +1416,7 @@
     "keyStatus": {
       "enabled": "有効",
       "disabled": "無効",
-      "active": "正常",
+      "active": "正常(アクティブ)",
       "expired": "期限切れ",
       "expiringSoon": "まもなく期限切れ",
       "keyEnabled": "キーが有効になりました",
@@ -1430,7 +1430,7 @@
     "userStatus": {
       "enabled": "有効",
       "disabled": "無効",
-      "active": "正常",
+      "active": "正常(アクティブ)",
       "expired": "期限切れ",
       "expiringSoon": "まもなく期限切れ",
       "userEnabled": "ユーザーが有効になりました",
@@ -1456,11 +1456,11 @@
         },
         "description": {
           "label": "メモ",
-          "placeholder": "メモを入力(任意)"
+          "placeholder": "メモを入力(任意)"
         },
         "tags": {
           "label": "ユーザータグ",
-          "placeholder": "タグを入力(Enterで追加)"
+          "placeholder": "タグを入力(Enterで追加)"
         },
         "providerGroup": {
           "label": "プロバイダーグループ",
@@ -1470,7 +1470,7 @@
           "label": "クライアント制限",
           "description": "このアカウントを使用できるCLI/IDEクライアントを制限します。空欄は制限なし。",
           "customLabel": "カスタムクライアントパターン",
-          "customPlaceholder": "パターンを入力(例:'xcode', 'my-ide')"
+          "customPlaceholder": "パターンを入力(例:'xcode', 'my-ide')"
         },
         "allowedModels": {
           "label": "モデル制限",
@@ -1533,7 +1533,7 @@
           "label": "Cache TTL上書き",
           "description": "cache_controlを含むリクエストに対してAnthropic prompt cache TTLを強制します。",
           "options": {
-            "inherit": "上書きしない(プロバイダー/クライアントに従う)",
+            "inherit": "上書きしない(プロバイダー/クライアントに従う)",
             "5m": "5m",
             "1h": "1h"
           }
@@ -1548,7 +1548,7 @@
         "daily": {
           "mode": {
             "fixed": "固定時間リセット",
-            "rolling": "ローリングウィンドウ(24時間)"
+            "rolling": "ローリングウィンドウ(24時間)"
           }
         },
         "overwriteHint": "このタイプは既に存在します。保存すると既存の値が上書きされます"

+ 1 - 1
messages/ja/index.ts

@@ -11,7 +11,7 @@ import notifications from "./notifications.json";
 import providerChain from "./provider-chain.json";
 import providers from "./providers.json";
 import quota from "./quota.json";
-import settings from "./settings.json";
+import settings from "./settings";
 import ui from "./ui.json";
 import usage from "./usage.json";
 import users from "./users.json";

+ 2 - 2
messages/ja/provider-chain.json

@@ -86,7 +86,7 @@
     "remaining": "残り{count}回",
     "status": "状態",
     "alreadyBroken": "すでに遮断済み",
-    "circuitTriggered": "⚠️ サーキットブレーカーが作動しました",
+    "circuitTriggered": "警告:サーキットブレーカーが作動しました",
     "errorDetails": "エラー詳細",
     "systemError": "システムエラー",
     "systemErrorFailed": "システムエラー(試行{attempt})",
@@ -97,7 +97,7 @@
     "errorMeaning": "意味: {meaning}",
     "meaning": "意味",
     "notCountedInCircuit": "このエラーはプロバイダーサーキットブレーカーにカウントされません",
-    "systemErrorNote": "ℹ️ このエラーはプロバイダーサーキットブレーカーにカウントされません",
+    "systemErrorNote": "注記:このエラーはプロバイダーサーキットブレーカーにカウントされません",
     "reselection": "プロバイダー再選択",
     "reselect": "プロバイダー再選択",
     "excluded": "除外済み: {providers}",

+ 0 - 2126
messages/ja/settings.json

@@ -1,2126 +0,0 @@
-{
-  "clientVersions": {
-    "description": "クライアントバージョン要件を管理し、ユーザーが最新の安定版を使用していることを確認します。VSCodeとCLIは個別に管理されます。",
-    "empty": {
-      "description": "過去7日間に認識可能なクライアントを使用したアクティブユーザーがいません",
-      "title": "クライアントデータなし"
-    },
-    "features": {
-      "activeWindow": "アクティブウィンドウ:",
-      "activeWindowDesc": "過去7日間にリクエストがあったユーザーのみを集計",
-      "autoDetect": "システムは各クライアントの最新安定版(GAバージョン)を自動検出します",
-      "blockOldVersion": "旧バージョンを使用するユーザーはHTTP 400エラーを受信し、サービスを継続使用できません",
-      "errorMessage": "エラーメッセージには現在のバージョンとアップグレード必要バージョン番号が含まれます",
-      "gaRule": "判定ルール:",
-      "gaRuleDesc": "1人以上のユーザーが使用しているバージョンをGAバージョンとみなします",
-      "recommendation": "推奨方法:",
-      "recommendationDesc": "まず下記のバージョン分布を確認し、新バージョンが安定していることを確認してから有効にしてください。",
-      "title": "機能説明",
-      "whatHappens": "有効化後の動作:"
-    },
-    "section": {
-      "distribution": {
-        "description": "過去7日間のアクティブユーザーのクライアントバージョン情報を表示します。各クライアントタイプごとにGAバージョンを独立して集計します。",
-        "title": "クライアントバージョン分布"
-      },
-      "settings": {
-        "description": "有効にすると、システムはクライアントバージョンを自動的に検出し、旧バージョンユーザーのリクエストをブロックします。",
-        "title": "アップグレードリマインダー設定"
-      }
-    },
-    "table": {
-      "currentGA": "現在のGAバージョン:",
-      "internalType": "内部タイプ:",
-      "lastActive": "最終アクティブ時間",
-      "latest": "最新",
-      "needsUpgrade": "アップグレード必要",
-      "noUsers": "ユーザーデータなし",
-      "status": "ステータス",
-      "unknown": "不明",
-      "user": "ユーザー",
-      "usersCount": "{count}名のユーザー",
-      "version": "現在のバージョン"
-    },
-    "title": "クライアント更新リマインダー",
-    "toggle": {
-      "description": "有効にすると、システムはクライアントバージョンを自動的に検出し、古いバージョンをブロックします。",
-      "disableSuccess": "クライアントバージョンチェックが無効になりました",
-      "enable": "クライアントバージョンチェックを有効にする",
-      "enableSuccess": "クライアントバージョンチェックが有効になりました",
-      "toggleFailed": "トグルに失敗しました"
-    }
-  },
-  "common": {
-    "cancel": "キャンセル",
-    "completed": "完了",
-    "confirm": "確認",
-    "copied": "キーをクリップボードにコピーしました",
-    "copy": "コピー",
-    "copyFailed": "コピーに失敗しました",
-    "create": "作成",
-    "creating": "作成中...",
-    "delete": "削除",
-    "disabled": "無効",
-    "edit": "編集",
-    "empty": "結果が見つかりません",
-    "enabled": "有効",
-    "error": "不明なエラー",
-    "failed": "失敗",
-    "loading": "読み込み中...",
-    "none": "なし(このバージョンを使用しているユーザーなし)",
-    "refresh": "更新",
-    "reset": "リセット",
-    "save": "保存",
-    "saving": "保存中...",
-    "submit": "送信",
-    "success": "成功",
-    "test": "テスト",
-    "testing": "テスト中...",
-    "unlimited": "無制限",
-    "unlimited_desc": "無制限",
-    "update": "更新",
-    "updating": "更新中..."
-  },
-  "config": {
-    "autoCleanup": "ログ自動クリーンアップ",
-    "autoCleanupDesc": "スケジュールに従って履歴ログを自動的にクリーンアップし、データベース容量を解放します。",
-    "description": "システムの基本パラメータを管理し、サイト表示と統計動作に影響します。",
-    "section": {
-      "siteParams": {
-        "title": "サイトパラメータ",
-        "description": "サイトタイトル、通貨表示単位、ダッシュボード統計表示ポリシーを設定します。"
-      },
-      "autoCleanup": {
-        "title": "ログ自動クリーンアップ",
-        "description": "スケジュールに従って履歴ログを自動的にクリーンアップし、データベース容量を解放します。"
-      }
-    },
-    "form": {
-      "allowGlobalView": "グローバル使用量表示を許可",
-      "allowGlobalViewDesc": "無効にすると、一般ユーザーはダッシュボードで自分のキーの使用統計のみを表示できます。",
-      "verboseProviderError": "詳細なプロバイダーエラー",
-      "verboseProviderErrorDesc": "有効にすると、すべてのプロバイダーが利用不可の場合に詳細なエラーメッセージ(プロバイダー数、レート制限の理由など)を返します。無効の場合は簡潔なエラーコードのみを返します。",
-      "interceptAnthropicWarmupRequests": "Warmup リクエストを遮断(Anthropic)",
-      "interceptAnthropicWarmupRequestsDesc": "有効にすると、Claude Code の Warmup プローブ要求は CCH が直接短い応答を返し、上流プロバイダーへのリクエストを回避します。ログには残りますが、課金/レート制限/統計には含まれません。",
-      "enableThinkingSignatureRectifier": "thinking 署名整流を有効化",
-      "enableThinkingSignatureRectifierDesc": "Anthropic プロバイダーで thinking 署名の不整合や不正なリクエストエラーが発生した場合、thinking 関連ブロックを削除して同一プロバイダーへ1回だけ再試行します(既定で有効)。",
-      "enableResponseFixer": "レスポンス整流を有効化",
-      "enableResponseFixerDesc": "上流応答の一般的な形式問題(エンコーディング、SSE、途切れた JSON)を自動修復します(既定で有効)。",
-      "responseFixerFixEncoding": "エンコーディングを修復",
-      "responseFixerFixEncodingDesc": "BOM/NULL バイトを除去し、無効な UTF-8 を正規化します。",
-      "responseFixerFixSseFormat": "SSE 形式を修復",
-      "responseFixerFixSseFormatDesc": "不足している data: 前置きを補い、改行を正規化し、よくあるフィールド形式を修正します。",
-      "responseFixerFixTruncatedJson": "途切れた JSON を修復",
-      "responseFixerFixTruncatedJsonDesc": "未閉じの括弧/引用符を補い、末尾カンマを除去し、必要に応じて null を補完します。",
-      "cleanupSchedule": "クリーンアップスケジュール",
-      "cleanupScheduleDesc": "自動クリーンアップの実行スケジュールを選択します",
-      "configUpdated": "システム設定が更新されました。ページが更新され、通貨表示の変更が適用されます。",
-      "currencyDisplay": "通貨表示単位",
-      "currencyDisplayPlaceholder": "通貨単位を選択",
-      "currencyDisplayDesc": "変更後、システムのすべてのページとAPIインターフェースは対応する通貨記号を使用します(記号のみ、為替レート変換なし)。",
-      "keepDays": "保持日数",
-      "keepDaysDesc": "指定した日数より古いログをクリーンアップします",
-      "saveFailed": "保存に失敗しました",
-      "saveSuccess": "正常に保存されました",
-      "saveError": "保存に失敗しました",
-      "saveSettings": "設定を保存",
-      "siteTitle": "サイトタイトル",
-      "siteTitlePlaceholder": "例:Claude Code Hub",
-      "siteTitleRequired": "サイトタイトルは空にできません",
-      "siteTitleDesc": "ブラウザタブのタイトルとシステムのデフォルト表示名を設定するために使用されます。",
-      "enableAutoCleanup": "自動クリーンアップを有効にする",
-      "enableAutoCleanupDesc": "スケジュールに従って履歴ログを自動的にクリーンアップします",
-      "cleanupRetentionDays": "保持日数",
-      "cleanupRetentionDaysRequired": "保持日数 *",
-      "cleanupRetentionDaysPlaceholder": "30",
-      "cleanupRetentionDaysDesc": "この日数を超えるログは自動的にクリーンアップされます(範囲:1-365日)",
-      "cleanupScheduleLabel": "実行時間(Cron)",
-      "cleanupScheduleRequired": "実行時間(Cron)*",
-      "cleanupSchedulePlaceholder": "0 2 * * *",
-      "cleanupScheduleCronDesc": "Cron式、デフォルト:0 2 * * *(毎日午前2時)",
-      "cleanupScheduleCronExample": "例:0 3 * * 0(毎週日曜日午前3時)",
-      "cleanupBatchSize": "バッチサイズ",
-      "cleanupBatchSizeRequired": "バッチサイズ *",
-      "cleanupBatchSizePlaceholder": "10000",
-      "cleanupBatchSizeDesc": "バッチごとに削除するレコード数(範囲:1000-100000、推奨10000)",
-      "saveConfig": "設定を保存",
-      "autoCleanupSaved": "自動クリーンアップ設定が保存されました",
-      "currencies": {
-        "USD": "$ 米ドル (USD)",
-        "CNY": "¥ 人民元 (CNY)",
-        "EUR": "€ ユーロ (EUR)",
-        "JPY": "¥ 日本円 (JPY)",
-        "GBP": "£ 英ポンド (GBP)",
-        "HKD": "HK$ 香港ドル (HKD)",
-        "TWD": "NT$ 新台湾ドル (TWD)",
-        "KRW": "₩ 韓国ウォン (KRW)",
-        "SGD": "S$ シンガポールドル (SGD)"
-      },
-      "billingModelSource": "課金モデルソース",
-      "billingModelSourcePlaceholder": "課金モデルソースを選択",
-      "billingModelSourceDesc": "モデルリダイレクト時に課金に使用するモデルを設定します。「リダイレクト前」はユーザーがリクエストした元のモデル、「リダイレクト後」は実際に呼び出されたモデルを使用します。",
-      "billingModelSourceOptions": {
-        "original": "リダイレクト前(元のモデル)",
-        "redirected": "リダイレクト後(実際のモデル)"
-      }
-    },
-    "siteSettings": "サイトパラメータ",
-    "siteSettingsDesc": "サイトタイトル、通貨表示単位、ダッシュボード統計表示方針を設定します。",
-    "title": "基本設定"
-  },
-  "data": {
-    "cleanup": {
-      "rangeLabel": "クリーンアップ範囲",
-      "range": {
-        "7days": "1週間前のログ(7日)",
-        "30days": "1ヶ月前のログ(30日)",
-        "90days": "3ヶ月前のログ(90日)",
-        "180days": "6ヶ月前のログ(180日)"
-      },
-      "rangeDescription": {
-        "7days": "1週間前",
-        "30days": "1ヶ月前",
-        "90days": "3ヶ月前",
-        "180days": "6ヶ月前",
-        "default": "{days}日前"
-      },
-      "willClean": "{range}のすべてのログレコードをクリーンアップします",
-      "button": "ログをクリーンアップ",
-      "confirmTitle": "ログクリーンアップの確認",
-      "confirmWarning": "この操作は{range}のすべてのログレコードを完全に削除し、復元できません。",
-      "previewLoading": "集計中...",
-      "previewCount": "{count}件のログレコードを削除します",
-      "previewError": "プレビュー情報を取得できません",
-      "statisticsRetained": "✓ 統計データは保持されます(トレンド分析用)",
-      "logsDeleted": "✗ ログ詳細は削除されます(リクエスト/レスポンス内容、エラー情報など)",
-      "backupRecommendation": "推奨:クリーンアップ前にデータベースバックアップをエクスポートして、データ復元が必要な場合に備えてください。",
-      "cancel": "キャンセル",
-      "confirm": "クリーンアップを確認",
-      "cleaning": "クリーンアップ中...",
-      "successMessage": "{count}件のログレコードをクリーンアップしました({batches}バッチ、所要時間{duration}秒)",
-      "failed": "クリーンアップ失敗",
-      "error": "ログのクリーンアップに失敗しました",
-      "descriptionWarning": "履歴ログデータをクリーンアップしてデータベースストレージを解放します。注:統計データは保持されますが、ログ詳細は完全に削除されます。"
-    },
-    "description": "データベースのバックアップと復元を管理し、完全なインポート/エクスポートとログクリーンアップをサポートします。",
-    "export": {
-      "button": "データベースをエクスポート",
-      "exporting": "エクスポート中...",
-      "successMessage": "データベースのエクスポートに成功しました!",
-      "failed": "エクスポート失敗",
-      "error": "データベースのエクスポートに失敗しました",
-      "descriptionFull": "完全なデータベースバックアップファイル(.dump形式)をエクスポートし、データ移行または復旧に使用できます。バックアップはPostgreSQL custom formatを使用し、自動圧縮され、異なるデータベースバージョンと互換性があります。"
-    },
-    "guide": {
-      "title": "使用説明と注意事項",
-      "items": {
-        "cleanup": {
-          "title": "ログクリーンアップ",
-          "description": "履歴ログを物理的に削除します(取り消せません)。統計テーブルは保持されます。クリーンアップ前にデータベースバックアップをエクスポートすることをお勧めします。"
-        },
-        "format": {
-          "title": "バックアップ形式",
-          "description": "PostgreSQL custom format(.dump)を使用し、自動圧縮で異なるデータベースバージョンと互換性があります。"
-        },
-        "overwrite": {
-          "title": "上書きモード",
-          "description": "インポート前にすべての既存データを削除します。完全復元に最適です。"
-        },
-        "merge": {
-          "title": "統合モード",
-          "description": "既存データを保持し、バックアップからのデータを挿入しようとします。主キーの競合がインポート失敗を引き起こす可能性があります。"
-        },
-        "safety": {
-          "title": "セキュリティ推奨",
-          "description": "インポート前に現在のデータベースをバックアップとしてエクスポートすることをお勧めします。"
-        },
-        "environment": {
-          "title": "環境要件",
-          "description": "Docker Composeデプロイメントが必要です。ローカル開発環境ではサポートされない可能性があります。"
-        }
-      }
-    },
-    "import": {
-      "selectFileLabel": "バックアップファイルを選択",
-      "fileSelected": "選択済み:{name}({size} MB)",
-      "fileError": ".dump形式のバックアップファイルを選択してください",
-      "noFileSelected": "最初にバックアップファイルを選択してください",
-      "cleanFirstLabel": "既存データをクリア(上書きモード)",
-      "cleanFirstDescription": "インポート前にすべての既存データを削除し、データベースがバックアップと完全に一致するようにします。チェックしない場合、データのマージを試みますが、主キーの競合により失敗する可能性があります。",
-      "button": "データベースをインポート",
-      "importing": "インポート中...",
-      "progressTitle": "インポート進行状況",
-      "confirmTitle": "データベースインポートの確認",
-      "confirmOverwrite": "「上書きモード」を選択しました。これにより、すべての既存データが削除された後、バックアップがインポートされます。",
-      "confirmMerge": "「マージモード」を選択しました。これにより、既存データを保持しながらバックアップのインポートを試みます。",
-      "warningOverwrite": "⚠️ 警告:この操作は元に戻せません。すべての現在のデータが完全に削除されます!",
-      "warningMerge": "⚠️ 注意:主キーの競合が存在する場合、インポートが失敗する可能性があります。",
-      "backupFile": "バックアップファイル:",
-      "backupRecommendation": "この操作を実行する前に、現在のデータベースをバックアップとしてエクスポートすることをお勧めします。",
-      "cancel": "キャンセル",
-      "confirm": "インポートを確認",
-      "successMessage": "データインポート完了!",
-      "failedMessage": "データインポート失敗、詳細ログを確認してください",
-      "error": "データベースのインポートに失敗しました",
-      "streamError": "レスポンスストリームを読み取れません",
-      "errorUnknown": "不明なエラー",
-      "descriptionFull": "バックアップファイルからデータベースを復元します。PostgreSQL custom format(.dump)形式のバックアップファイルをサポートします。"
-    },
-    "status": {
-      "loading": "読み込み中...",
-      "error": "データベースステータスの取得に失敗しました",
-      "retry": "再試行",
-      "connected": "データベース接続正常",
-      "unavailable": "データベース利用不可",
-      "tables": "{count} テーブル"
-    },
-    "title": "データ管理",
-    "section": {
-      "status": {
-        "title": "データベースステータス",
-        "description": "現在のデータベース接続状態と基本情報を表示します。"
-      },
-      "cleanup": {
-        "title": "ログクリーンアップ",
-        "description": "履歴ログデータをクリーンアップしてデータベースストレージを解放します。注:統計データは保持されますが、ログ詳細は完全に削除されます。"
-      },
-      "export": {
-        "title": "データエクスポート",
-        "description": "完全なデータベースバックアップファイル(.dump形式)をエクスポートし、データ移行または復旧に使用できます。"
-      },
-      "import": {
-        "title": "データインポート",
-        "description": "バックアップファイルからデータベースを復元します。PostgreSQL custom format(.dump)形式のバックアップファイルをサポートします。"
-      }
-    }
-  },
-  "errors": {
-    "saveSuccess": "保存に成功しました",
-    "saveFailed": "保存に失敗しました",
-    "saveFailed_error": "設定の保存に失敗しました",
-    "addSuccess": "追加に成功しました",
-    "addFailed": "プロバイダーの追加に失敗しました",
-    "editSuccess": "更新に成功しました",
-    "editFailed": "プロバイダーの更新に失敗しました",
-    "deleteSuccess": "削除に成功しました",
-    "deleteFailed": "プロバイダーの削除に失敗しました",
-    "syncSuccess": "同期に成功しました",
-    "syncFailed": "同期に失敗しました",
-    "testFailed": "テストに失敗しました",
-    "testFailedRetry": "テストに失敗しました。再試行してください",
-    "loadFailed": "通知設定の読み込みに失敗しました",
-    "unknownError": "操作中に例外が発生しました"
-  },
-  "logs": {
-    "description": "システムログレベルを動的に調整してロギング詳細度をリアルタイムで制御します。",
-    "subtitle": "ログレベルコントロール",
-    "subtitleDesc": "変更はすぐに有効になります、再起動不要。本番環境でのトラブルシューティングに便利です。",
-    "section": {
-      "title": "ログレベルコントロール",
-      "description": "変更はすぐに有効になります、サービス再起動不要。"
-    },
-    "levels": {
-      "fatal": {
-        "label": "Fatal",
-        "description": "致命的エラーのみ"
-      },
-      "error": {
-        "label": "Error",
-        "description": "エラーメッセージ"
-      },
-      "warn": {
-        "label": "Warn",
-        "description": "警告 + エラー"
-      },
-      "info": {
-        "label": "Info",
-        "description": "主要なビジネスイベント + 警告 + エラー(本番環境推奨)"
-      },
-      "debug": {
-        "label": "Debug",
-        "description": "デバッグ情報 + 全レベル(開発環境推奨)"
-      },
-      "trace": {
-        "label": "Trace",
-        "description": "非常に詳細なトレース + 全レベル"
-      }
-    },
-    "form": {
-      "currentLevel": "現在のログレベル",
-      "selectLevel": "ログレベルを選択",
-      "save": "設定を保存",
-      "saving": "保存中...",
-      "success": "ログレベルを設定しました: {level}",
-      "failed": "設定に失敗しました",
-      "failedError": "ログレベルの設定に失敗しました",
-      "fetchFailed": "ログレベルの取得に失敗しました",
-      "effectiveImmediately": "ログレベルの変更はすぐに有効になります、サービス再起動不要。",
-      "levelGuideTitle": "ログレベルガイド",
-      "levelGuideFatal": "Fatal/Error: エラーのみ表示、最小限のログ、高負荷本番環境に適しています",
-      "levelGuideWarn": "Warn: 警告(レート制限、サーキットブレーカー開放など)+ エラーを含む",
-      "levelGuideInfo": "Info(本番環境推奨): 主要なビジネスイベント(プロバイダー選択、セッション再利用、価格同期)+ 警告 + エラーを表示",
-      "levelGuideDebug": "Debug(開発環境推奨): 詳細なデバッグ情報を含む、トラブルシューティングに適しています",
-      "levelGuideTrace": "Trace: 非常に詳細なトレース情報、すべての詳細を含む",
-      "changeNotice": "現在のレベルは {current} です、保存後 {selected} に切り替わります"
-    },
-    "title": "ログ管理"
-  },
-  "nav": {
-    "apiDocs": "API文書",
-    "clientVersions": "更新通知",
-    "config": "設定",
-    "data": "データ",
-    "errorRules": "エラー",
-    "feedback": "報告",
-    "docs": "ドキュメント",
-    "logs": "ログ",
-    "notifications": "通知",
-    "prices": "価格表",
-    "providers": "供給元",
-    "sensitiveWords": "フィルター",
-    "requestFilters": "リクエスト"
-  },
-  "notifications": {
-    "title": "プッシュ通知",
-    "description": "Webhook プッシュ通知を設定",
-  "global": {
-    "title": "通知マスタースイッチ",
-    "description": "すべてのプッシュ通知機能を有効または無効にする",
-    "enable": "プッシュ通知を有効にする",
-    "legacyModeTitle": "互換モード",
-    "legacyModeDescription": "現在は旧来の単一URL通知設定を使用しています。プッシュ先を作成するとマルチターゲットモードに切り替わります。"
-  },
-  "targets": {
-    "title": "プッシュ先",
-    "description": "プッシュ先を管理します。WeCom、Feishu、DingTalk、Telegram、カスタムWebhookに対応。",
-    "add": "追加",
-    "update": "保存",
-    "edit": "編集",
-    "delete": "削除",
-    "deleteConfirmTitle": "プッシュ先を削除",
-    "deleteConfirm": "このプッシュ先を削除しますか?関連するバインドも削除されます。",
-    "enable": "有効化",
-    "statusEnabled": "有効",
-    "statusDisabled": "無効",
-    "lastTestAt": "最終テスト",
-    "lastTestNever": "未テスト",
-    "lastTestSuccess": "テスト成功",
-    "lastTestFailed": "テスト失敗",
-    "test": "テスト",
-    "testSelectType": "テスト種類を選択",
-    "emptyHint": "プッシュ先がありません。「追加」で作成してください。",
-    "created": "プッシュ先を作成しました",
-    "updated": "プッシュ先を更新しました",
-    "deleted": "プッシュ先を削除しました",
-    "bindingsSaved": "バインドを保存しました"
-  },
-  "targetDialog": {
-    "createTitle": "プッシュ先を追加",
-    "editTitle": "プッシュ先を編集",
-    "name": "名前",
-    "namePlaceholder": "例: Ops グループ",
-    "type": "プラットフォーム",
-    "selectType": "プラットフォームを選択",
-    "enable": "有効化",
-    "webhookUrl": "Webhook URL",
-    "webhookUrlPlaceholder": "https://example.com/webhook",
-    "telegramBotToken": "Telegram Bot Token",
-    "telegramBotTokenPlaceholder": "例: 123456:ABCDEF...",
-    "telegramChatId": "Telegram Chat ID",
-    "telegramChatIdPlaceholder": "例: -1001234567890",
-    "dingtalkSecret": "DingTalk シークレット",
-    "dingtalkSecretPlaceholder": "任意(署名用)",
-    "customHeaders": "カスタムヘッダー(JSON)",
-    "customHeadersPlaceholder": "{\"X-Token\":\"...\"}",
-    "errors": {
-      "headersInvalidJson": "Headers は有効な JSON である必要があります",
-      "headersMustBeObject": "Headers は JSON オブジェクトである必要があります",
-      "headersValueMustBeString": "Headers の値は文字列である必要があります"
-    },
-    "types": {
-      "wechat": "WeCom",
-      "feishu": "Feishu",
-      "dingtalk": "DingTalk",
-      "telegram": "Telegram",
-      "custom": "カスタムWebhook"
-    },
-    "proxy": {
-      "title": "プロキシ",
-      "toggle": "プロキシ設定を切り替え",
-      "url": "プロキシURL",
-      "urlPlaceholder": "http://127.0.0.1:7890",
-      "fallbackToDirect": "プロキシ失敗時に直結へフォールバック"
-    }
-  },
-  "bindings": {
-    "title": "バインド",
-    "noTargets": "プッシュ先がありません",
-    "bindTarget": "プッシュ先をバインド",
-    "enable": "有効",
-    "enableType": "この通知を有効化",
-    "advanced": "詳細",
-    "scheduleCron": "Cron",
-    "scheduleCronPlaceholder": "例: 0 9 * * *",
-    "scheduleTimezone": "タイムゾーン",
-    "templateOverride": "テンプレート上書き",
-    "editTemplateOverride": "上書きを編集",
-    "templateOverrideTitle": "テンプレート上書きを編集",
-    "boundCount": "バインド: {count}",
-    "enabledCount": "有効: {count}"
-  },
-  "templateEditor": {
-    "title": "テンプレート(JSON)",
-    "placeholder": "JSON テンプレートを入力...",
-    "jsonInvalid": "JSON が不正です",
-    "placeholders": "プレースホルダー",
-    "insert": "挿入"
-  },
-  "circuitBreaker": {
-    "title": "サーキットブレーカーアラート",
-      "description": "プロバイダーが完全に遮断された時に即座にアラートを送信",
-      "enable": "サーキットブレーカーアラートを有効にする",
-      "webhook": "Webhook URL",
-      "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...",
-      "test": "接続テスト"
-    },
-    "dailyLeaderboard": {
-      "title": "日次ユーザー消費ランキング",
-      "description": "毎日定時でユーザー消費トップNランキングを送信",
-      "enable": "日次ランキングを有効にする",
-      "webhook": "Webhook URL",
-      "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...",
-      "time": "送信時刻",
-      "timePlaceholder": "09:00",
-      "timeError": "時刻形式エラー、HH:mm形式である必要があります",
-      "topN": "トップN件表示",
-      "test": "接続テスト"
-    },
-    "costAlert": {
-      "title": "コストアラート",
-      "description": "ユーザー/プロバイダーの消費がクォータしきい値を超えた時にアラートをトリガー",
-      "enable": "コストアラートを有効にする",
-      "webhook": "Webhook URL",
-      "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...",
-      "webhookTypeWeCom": "WeCom",
-      "webhookTypeFeishu": "Feishu",
-      "webhookTypeUnknown": "不明なプラットフォームです。WeComまたはFeishuのWebhook URLを使用してください",
-      "threshold": "アラートしきい値",
-      "thresholdLabel": "アラートしきい値: {percent}%",
-      "thresholdHelp": "消費がクォータの{percent}%に達した時にアラート",
-      "interval": "チェック間隔(分)",
-      "test": "接続テスト"
-    },
-    "form": {
-      "save": "設定を保存",
-      "saving": "保存中...",
-      "loading": "読み込み中...",
-      "success": "通知設定を保存し、タスクを再スケジュールしました",
-      "saveFailed": "保存に失敗しました",
-      "saveError": "設定の保存に失敗しました",
-      "loadError": "通知設定の読み込みに失敗しました",
-      "webhookRequired": "まずWebhook URLを入力してください",
-      "testSuccess": "テストメッセージを送信しました",
-      "testFailed": "テストに失敗しました",
-      "testFailedRetry": "テストに失敗しました。再試行してください",
-      "testError": "接続テストに失敗しました",
-      "testNoResult": "テストは成功しましたが、結果が返されませんでした"
-    }
-  },
-  "prices": {
-    "title": "価格表",
-    "description": "プラットフォーム基本設定とモデル価格を管理します",
-    "section": {
-      "title": "モデル価格",
-      "description": "AIモデルの価格設定を管理します"
-    },
-    "searchPlaceholder": "モデル名を検索...",
-    "filters": {
-      "all": "すべて",
-      "local": "ローカル",
-      "anthropic": "Anthropic",
-      "openai": "OpenAI",
-      "vertex": "Vertex"
-    },
-    "badges": {
-      "local": "ローカル"
-    },
-    "capabilities": {
-      "assistantPrefill": "アシスタント事前入力",
-      "computerUse": "コンピューター利用",
-      "functionCalling": "関数呼び出し",
-      "pdfInput": "PDF入力",
-      "promptCaching": "プロンプトキャッシュ",
-      "reasoning": "推論",
-      "responseSchema": "レスポンススキーマ",
-      "toolChoice": "ツール選択",
-      "vision": "ビジョン",
-      "statusSupported": "対応",
-      "statusUnsupported": "未対応",
-      "tooltip": "{label}: {status}"
-    },
-    "sync": {
-      "button": "クラウド価格表を同期",
-      "syncing": "同期中...",
-      "checking": "競合を確認中...",
-      "successWithChanges": "価格表を更新: {added}件追加、{updated}件更新、{unchanged}件変化なし",
-      "successNoChanges": "価格表は最新です。更新の必要はありません",
-      "failed": "同期に失敗しました",
-      "failedError": "同期に失敗しました: {error}",
-      "failedNoResult": "価格表は更新されましたが結果が返されていません",
-      "noModels": "モデル価格が見つかりません",
-      "partialFailure": "一部更新が成功しましたが、{failed}件のモデルが失敗しました",
-      "failedModels": "失敗モデル: {models}",
-      "skippedConflicts": "{count}件の手動モデルをスキップしました"
-    },
-    "conflict": {
-      "title": "上書きする項目を選択",
-      "description": "以下のモデルには手動で設定された価格があります。チェックした項目はLiteLLM価格で上書きされ、チェックしない項目は現在のままです",
-      "searchPlaceholder": "モデルを検索...",
-      "table": {
-        "modelName": "モデル",
-        "manualPrice": "手動価格",
-        "litellmPrice": "LiteLLM価格",
-        "action": "操作"
-      },
-      "viewDiff": "差異を表示",
-      "diffTitle": "価格差異",
-      "diff": {
-        "field": "フィールド",
-        "manual": "手動",
-        "litellm": "LiteLLM",
-        "inputPrice": "入力価格",
-        "outputPrice": "出力価格",
-        "imagePrice": "画像価格",
-        "provider": "プロバイダー",
-        "mode": "タイプ"
-      },
-      "pagination": {
-        "showing": "{from}〜{to}件を表示(全{total}件)"
-      },
-      "selectedCount": "{count}/{total}件のモデルを選択",
-      "noMatch": "一致するモデルが見つかりません",
-      "noConflicts": "競合なし",
-      "applyOverwrite": "上書きを適用",
-      "applying": "適用中..."
-    },
-    "table": {
-      "modelName": "モデル名",
-      "provider": "プロバイダー",
-      "capabilities": "機能",
-      "price": "価格",
-      "inputPrice": "入力価格 ($/M)",
-      "outputPrice": "出力価格 ($/M)",
-      "priceInput": "入力",
-      "priceOutput": "出力",
-      "pricePerRequest": "回",
-      "cacheReadPrice": "キャッシュ読み取り ($/M)",
-      "cacheCreationPrice": "キャッシュ作成 ($/M)",
-      "cache5m": "5m",
-      "cache1h": "1h+",
-      "copyModelId": "モデルIDをコピー",
-      "updatedAt": "更新日時",
-      "actions": "操作",
-      "typeChat": "チャット",
-      "typeImage": "画像生成",
-      "typeCompletion": "補完",
-      "typeUnknown": "不明",
-      "loading": "読み込み中...",
-      "noMatch": "一致するモデルが見つかりません",
-      "noDataTitle": "価格データがありません",
-      "noDataHint": "システムは組み込み価格表を持っています。上のボタンを使用して同期または更新してください。"
-    },
-    "pagination": {
-      "showing": "{from}〜{to}件を表示(全{total}件)",
-      "previous": "前へ",
-      "next": "次へ",
-      "perPageLabel": "1ページあたり",
-      "perPage": "1ページあたり{size}件"
-    },
-    "stats": {
-      "totalModels": "合計{count}個のモデル",
-      "searchResults": "{count}件の検索結果",
-      "lastUpdated": "最終更新: {time}"
-    },
-    "dialog": {
-      "title": "モデル価格表を更新",
-      "description": "モデル価格データを含むJSONまたはTOMLファイルを選択してアップロード",
-      "selectFile": "JSON/TOMLファイルをクリックして選択、またはドラッグしてください",
-      "fileSizeLimit": "ファイルサイズは10MBを超えることはできません",
-      "fileSizeLimitSmall": "ファイルサイズは10MB以下です",
-      "invalidFileType": "JSONまたはTOML形式のファイルを選択してください",
-      "fileTooLarge": "ファイルサイズが10MBを超えています",
-      "upload": "アップロードして更新",
-      "uploading": "アップロード中...",
-      "updatePriceTable": "価格表を更新",
-      "updating": "更新中...",
-      "selectJson": "ファイルを選択",
-      "updateSuccess": "価格表が正常に更新されました。{count}個のモデルを更新しました",
-      "updateFailed": "更新に失敗しました",
-      "systemHasBuiltIn": "システムは組み込み価格表を持っています",
-      "manualDownload": "手動でダウンロードすることもできます",
-      "latestPriceTable": "クラウド価格表",
-      "andUploadViaButton": "、上のボタンでアップロードしてください",
-      "cloudModelCountLoading": "クラウドモデル数を読み込み中...",
-      "cloudModelCountFailed": "クラウドモデル数の読み込みに失敗しました",
-      "supportedModels": "現在{count}個のモデルをサポート",
-      "results": {
-        "title": "更新結果",
-        "total": "合計: {total}個のモデル",
-        "success": "成功: {success}",
-        "failed": "失敗: {failed}",
-        "skipped": "スキップ: {skipped}",
-        "more": " (+{count})",
-        "details": "詳細",
-        "viewDetails": "詳細ログを表示"
-      }
-    },
-    "addModel": "モデルを追加",
-    "editModel": "モデルを編集",
-    "deleteModel": "モデルを削除",
-    "addModelDescription": "新しいモデル価格設定を手動で追加します",
-    "editModelDescription": "モデルの価格設定を編集します",
-    "deleteConfirm": "モデル {name} を削除してもよろしいですか?この操作は元に戻せません。",
-    "form": {
-      "modelName": "モデルID",
-      "modelNamePlaceholder": "例: gpt-5.2-codex",
-      "modelNameRequired": "モデルIDは必須です",
-      "displayName": "表示名(任意)",
-      "displayNamePlaceholder": "例: GPT-5.2 Codex",
-      "type": "タイプ",
-      "provider": "プロバイダー",
-      "providerPlaceholder": "例: openai",
-      "requestPrice": "呼び出し単価 ($/request)",
-      "inputPrice": "入力価格 ($/M tokens)",
-      "outputPrice": "出力価格 ($/M tokens)",
-      "outputPriceImage": "出力価格 ($/image)",
-      "cacheReadPrice": "キャッシュ読み取り価格 ($/M tokens)",
-      "cacheCreationPrice5m": "キャッシュ作成価格(5m,$/M tokens)",
-      "cacheCreationPrice1h": "キャッシュ作成価格(1h+,$/M tokens)"
-    },
-    "drawer": {
-      "prefillLabel": "既存モデルを検索してプリフィル",
-      "prefillEmpty": "一致するモデルが見つかりません",
-      "prefillFailed": "検索に失敗しました",
-      "promptCachingHint": "モデルがキャッシュに対応している場合のみ有効化し、下のキャッシュ価格を設定してください",
-      "cachePricingTitle": "キャッシュ価格"
-    },
-    "actions": {
-      "edit": "編集",
-      "more": "その他の操作",
-      "delete": "削除"
-    },
-    "toast": {
-      "createSuccess": "モデルを追加しました",
-      "updateSuccess": "モデルを更新しました",
-      "deleteSuccess": "モデルを削除しました",
-      "saveFailed": "保存に失敗しました",
-      "deleteFailed": "削除に失敗しました"
-    }
-  },
-  "providers": {
-    "add": "プロバイダーを追加",
-    "addFailed": "プロバイダーの追加に失敗しました",
-    "addProvider": "プロバイダーを追加",
-    "addSuccess": "プロバイダーが正常に追加されました",
-    "autoSort": {
-      "button": "優先度を自動ソート",
-      "dialogTitle": "プロバイダー優先度の自動ソート",
-      "dialogDescription": "コスト倍率に基づいて優先度を自動割り当て(低コスト = 高優先度)",
-      "changeCount": "{count} 件のプロバイダーが更新されます",
-      "noChanges": "変更不要(ソート済み)",
-      "costMultiplierHeader": "コスト倍率",
-      "priorityHeader": "優先度",
-      "providersHeader": "プロバイダー",
-      "changesTitle": "変更詳細",
-      "providerHeader": "プロバイダー",
-      "priorityChangeHeader": "優先度変更",
-      "confirm": "変更を適用",
-      "success": "{count} 件のプロバイダーの優先度を更新しました",
-      "error": "優先度の更新に失敗しました"
-    },
-    "circuitBroken": "サーキットブレーカー作動中",
-    "clone": "プロバイダーを複製",
-    "cloneFailed": "コピーに失敗しました",
-    "confirmDelete": "このプロバイダーを削除してもよろしいですか?",
-    "confirmDeleteDesc": "プロバイダー「{name}」を削除してもよろしいですか?この操作は元に戻せません。",
-    "confirmDeleteProvider": "プロバイダーの削除を確認しますか?",
-    "confirmDeleteProviderDesc": "サービスプロバイダー「{name}」を削除してもよろしいですか?この操作は復元できません。",
-    "createProvider": "サービスプロバイダーを追加",
-    "delete": "プロバイダーを削除",
-    "deleteFailed": "プロバイダーの削除に失敗しました",
-    "deleteSuccess": "削除成功",
-    "description": "APIサービスプロバイダーを設定し、可用性ステータスを維持します。",
-    "disabledStatus": "無効",
-    "displayCount": "{filtered} / {total}個のプロバイダーを表示",
-    "edit": "プロバイダーを編集",
-    "editFailed": "プロバイダーの更新に失敗しました",
-    "editProvider": "サービスプロバイダーを編集",
-    "enabledStatus": "有効",
-    "form": {
-      "proxyTest": {
-        "fillUrlFirst": "まずプロバイダーURLを入力してください",
-        "testFailed": "テスト失敗",
-        "testFailedRetry": "テストに失敗しました。再試行してください",
-        "noResult": "テスト成功ですが結果が返されませんでした",
-        "connectionSuccess": "接続成功",
-        "connectionFailed": "接続失敗",
-        "viaProxy": "(プロキシ経由)",
-        "viaDirect": "(直接接続)",
-        "responseTime": "応答時間:",
-        "statusCode": "ステータスコード:",
-        "connectionMethod": "接続方式:",
-        "proxy": "プロキシ",
-        "direct": "直接接続",
-        "errorType": "エラータイプ:",
-        "testing": "テスト中...",
-        "testConnection": "接続テスト",
-        "timeoutError": "接続タイムアウト(5秒)。以下を確認してください:\n1. プロキシサーバーにアクセスできるか\n2. プロキシアドレスとポートが正しいか\n3. プロキシ認証情報が正しいか",
-        "proxyError": "プロキシエラー:",
-        "networkError": "ネットワークエラー:"
-      },
-      "apiTest": {
-        "fillUrlFirst": "まずプロバイダーURLを入力してください",
-        "invalidUrl": "プロバイダーURLが無効です(http/httpsのみ対応)",
-        "fillKeyFirst": "まずAPIキーを入力してください",
-        "testFailed": "テスト失敗",
-        "testFailedRetry": "テスト失敗、再試行してください",
-        "noResult": "テスト成功ですが結果が返されませんでした",
-        "testSuccess": "モデルテスト成功",
-        "testApi": "プロバイダーモデルテスト",
-        "testing": "テスト中...",
-        "apiFormat": "プロバイダータイプ",
-        "selectApiFormat": "テストするプロバイダータイプを選択",
-        "apiFormatDesc": "手動で変更しない限り、ルーティング設定のプロバイダータイプと同期",
-        "formatAnthropicMessages": "Claude (Anthropic Messages API)",
-        "formatOpenAIChat": "OpenAI Compatible",
-        "formatOpenAIResponses": "Codex (Response API)",
-        "testModel": "テストモデル",
-        "testModelDesc": "空欄の場合はデフォルトモデルを使用、手動入力も可能",
-        "requestConfig": "リクエスト設定",
-        "presetConfig": "プリセット",
-        "customConfig": "カスタム",
-        "selectPreset": "プリセットテンプレートを選択",
-        "presetDesc": "プリセットテンプレートには、リレーサービス検証用の本物のCLIリクエストパターンが含まれています",
-        "customPayloadPlaceholder": "{\"model\": \"...\", \"messages\": [...]}",
-        "customPayloadDesc": "カスタムJSONペイロードを入力してデフォルトのリクエストボディを上書き",
-        "successContains": "成功検出キーワード",
-        "successContainsPlaceholder": "pong",
-        "successContainsDesc": "成功と見なすには、レスポンスにこのキーワードが含まれている必要があります",
-        "model": "モデル",
-        "responseModel": "応答モデル",
-        "responseTime": "応答時間",
-        "usage": "トークン使用量",
-        "response": "応答内容",
-        "error": "エラーメッセージ",
-        "unknown": "不明",
-        "viewDetails": "詳細を見る",
-        "copySuccess": "クリップボードにコピーしました",
-        "copyFailed": "コピー失敗",
-        "copyResult": "結果をコピー",
-        "close": "閉じる",
-        "success": "成功",
-        "failed": "失敗",
-        "streamInfo": "ストリーム応答情報",
-        "chunksReceived": "受信したチャンク",
-        "streamFormat": "ストリーム形式",
-        "streamResponse": "ストリーム応答",
-        "chunksCount": "{count} チャンク受信 ({format})",
-        "truncatedPreview": "先頭 {length} 文字を表示、全文はコピーして確認",
-        "truncatedBrief": "先頭 {length} 文字を表示、全文は「詳細を見る」をクリック",
-        "timeout": {
-          "label": "タイムアウト(秒)",
-          "desc": "テストリクエストの最大待機時間(5〜120秒)",
-          "geminiHint": "、Gemini Thinkingモデルは60秒以上を推奨"
-        },
-        "geminiAuthFallback": {
-          "warning": "ヘッダー認証に失敗し、URLパラメータ認証を使用しました",
-          "desc": "実際のプロキシ転送はヘッダー認証のみを使用するため、リクエストが失敗する可能性があります"
-        },
-        "copyFormat": {
-          "testResult": "テスト結果",
-          "message": "メッセージ",
-          "errorDetails": "エラー詳細"
-        },
-        "disclaimer": {
-          "title": "注意",
-          "realRequest": "テストはプロバイダーに実際のリクエストを送信し、少量のクォータを消費する可能性があります",
-          "resultReference": "プロバイダーによって結果が異なる場合があり、参考用です",
-          "confirmConfig": "プロバイダーURL、APIキー、モデル設定を確認してください"
-        },
-        "resultCard": {
-          "status": {
-            "green": "利用可能",
-            "yellow": "不安定",
-            "red": "利用不可"
-          },
-          "dialogTitle": "プロバイダーテスト詳細",
-          "validation": {
-            "title": "三層検証詳細",
-            "http": {
-              "title": "Tier 1: HTTPステータス",
-              "statusCode": "ステータスコード",
-              "passed": "2xx/3xx 成功",
-              "failed": "4xx/5xx 失敗"
-            },
-            "latency": {
-              "title": "Tier 2: レイテンシ閾値",
-              "actual": "実際のレイテンシ",
-              "passed": "閾値内",
-              "failed": "閾値超過"
-            },
-            "content": {
-              "title": "Tier 3: コンテンツ検証",
-              "target": "ターゲット",
-              "passed": "ターゲット文字列を含む",
-              "failed": "ターゲットが見つかりません"
-            },
-            "passed": "合格",
-            "failed": "失敗",
-            "timeout": "タイムアウト"
-          },
-          "labels": {
-            "http": "HTTP",
-            "latency": "レイテンシ",
-            "content": "コンテンツ",
-            "model": "モデル",
-            "firstByte": "最初のバイト",
-            "totalLatency": "合計レイテンシ",
-            "error": "エラー",
-            "responsePreview": "応答プレビュー"
-          },
-          "timing": {
-            "title": "タイミング情報",
-            "totalLatency": "合計レイテンシ",
-            "firstByte": "最初のバイト",
-            "testedAt": "テスト日時"
-          },
-          "tokenUsage": {
-            "title": "トークン使用量",
-            "input": "入力",
-            "output": "出力",
-            "cacheCreation": "キャッシュ作成",
-            "cacheRead": "キャッシュ読取"
-          },
-          "streamInfo": {
-            "title": "ストリーム応答情報",
-            "isStreaming": "ストリーミング",
-            "chunksCount": "チャンク数",
-            "yes": "はい",
-            "no": "いいえ"
-          },
-          "rawResponse": {
-            "title": "生のレスポンスボディ",
-            "hint": "ここに生のレスポンス内容が表示されます。キーワードがレスポンスに含まれているか確認できます。"
-          },
-          "errorDetails": {
-            "title": "エラー詳細",
-            "type": "エラータイプ"
-          },
-          "copyText": {
-            "status": "ステータス",
-            "message": "メッセージ",
-            "latency": "レイテンシ",
-            "httpStatus": "HTTPステータス",
-            "model": "モデル",
-            "usage": "使用量",
-            "inputOutput": "入力 {input} / 出力 {output} トークン",
-            "response": "応答",
-            "error": "エラー",
-            "testedAt": "テスト日時",
-            "validationDetails": "検証詳細",
-            "httpCheck": "HTTPチェック",
-            "latencyCheck": "レイテンシチェック",
-            "contentCheck": "コンテンツ検証"
-          },
-          "judgment": "判定"
-        }
-      },
-      "urlPreview": {
-        "title": "URL結合プレビュー",
-        "invalidUrl": "無効なURL形式",
-        "invalidUrlDesc": "有効なHTTP/HTTPSアドレスを入力してください",
-        "duplicatePath": "重複パス検出",
-        "copy": "コピー",
-        "copySuccess": "{name} をクリップボードにコピーしました",
-        "copyFailed": "コピーに失敗しました"
-      },
-      "modelSelect": {
-        "allowAllModels": "すべての {type} モデルを許可",
-        "selectedCount": "{count} 個のモデルを選択済み",
-        "searchPlaceholder": "モデル名を検索...",
-        "loading": "読み込み中...",
-        "notFound": "モデルが見つかりません",
-        "selectAll": "すべて選択 ({count})",
-        "clear": "クリア",
-        "manualAdd": "手動でモデルを追加",
-        "manualPlaceholder": "モデル名を入力(例:gpt-5-turbo)",
-        "manualDesc": "任意のモデル名を追加できます(価格表のモデルに限定されません)",
-        "claude": "Claude",
-        "openai": "OpenAI",
-        "gemini": "Gemini",
-        "sourceUpstream": "上流",
-        "sourceUpstreamDesc": "モデルリストは上流プロバイダーAPIから取得",
-        "sourceFallback": "ローカル",
-        "sourceFallbackDesc": "ローカル価格表のモデルリストを使用(上流が利用不可または未対応)",
-        "refresh": "モデルリストを更新"
-      },
-      "modelRedirect": {
-        "currentRules": "現在のルール ({count})",
-        "addNewRule": "新規ルールを追加",
-        "sourceModel": "ユーザーがリクエストするモデル",
-        "targetModel": "実際に転送されるモデル",
-        "sourcePlaceholder": "例:claude-sonnet-4-5-20250929",
-        "targetPlaceholder": "例:glm-4.6",
-        "add": "追加",
-        "sourceEmpty": "ソースモデル名を入力してください",
-        "targetEmpty": "ターゲットモデル名を入力してください",
-        "alreadyExists": "モデル \"{model}\" のリダイレクトルールは既に存在します",
-        "description": "Claude Code クライアントがリクエストするモデル(例:claude-sonnet-4.5)を、上流プロバイダーが実際にサポートするモデル(例:glm-4.6、gemini-pro)にリダイレクトします。コスト最適化やサードパーティAIサービスへの接続に使用します。",
-        "emptyState": "リダイレクトルールがありません。ルールを追加すると、システムは自動的にリクエスト内のモデル名を書き換えます。"
-      },
-      "addRedirect": "リダイレクトを追加",
-      "allowAllModels": "✓ すべてのモデルを許可(推奨)",
-      "apiAddress": "API 地址",
-      "apiAddressPlaceholder": "例如: https://open.bigmodel.cn/api/anthropic",
-      "apiAddressRequired": "API 地址 *",
-      "apiKey": "APIキー",
-      "apiKeyCurrent": "当前密钥:",
-      "apiKeyLeaveEmpty": "(留空不更改)",
-      "apiKeyLeaveEmptyDesc": "留空则不更改密钥",
-      "apiKeyOptional": "現在のキーを保持する場合は空のままにしてください",
-      "apiKeyPlaceholder": "APIキーを入力",
-      "apiKeyRequired": "API 密钥 *",
-      "baseUrl": "ベースURL",
-      "baseUrlPlaceholder": "例:https://open.bigmodel.cn/api/anthropic",
-      "baseUrlRequired": "プロバイダーURLを入力してください",
-      "circuitBreakerConfig": "サーキットブレーカー設定",
-      "circuitBreakerConfigSummary": "{failureThreshold} 回失敗 / {openDuration} 分間ブレーク / {successThreshold} 回成功で回復 / 各プロバイダー最大 {maxRetryAttempts} 回試行",
-      "circuitBreakerDesc": "連続失敗時に自動的にブレークして全体の品質を保護します",
-      "clearSearch": "検索をクリア",
-      "codexInstructions": "Codexインストラクション方針",
-      "codexInstructionsAuto": "自動(推奨)",
-      "codexInstructionsDesc": "(スケジューリング方針を決定)",
-      "codexInstructionsForce": "公式を強制",
-      "codexInstructionsKeep": "元の値を保持",
-      "codexStrategyAutoDesc": "透传客户端 instructions,400 错误时自动重试官方 prompt",
-      "codexStrategyAutoLabel": "自动 (推荐)",
-      "codexStrategyConfig": "Codex Instructions 策略",
-      "codexStrategyConfigAuto": "自动 (推荐)",
-      "codexStrategyConfigForce": "强制官方",
-      "codexStrategyConfigKeep": "透传原样",
-      "codexStrategyDesc": "控制如何处理 Codex 请求的 instructions 字段,影响与上游中转站的兼容性",
-      "codexStrategyForceDesc": "始终使用官方 Codex CLI instructions(约 4000+ 字)",
-      "codexStrategyForceLabel": "强制官方",
-      "codexStrategyHint": "提示: 部分严格的 Codex 中转站(如 88code、foxcode)需要官方 instructions,选择\"自动\"或\"强制官方\"策略",
-      "codexStrategyKeepDesc": "始终透传客户端 instructions,不自动重试(适用于宽松中转站)",
-      "codexStrategyKeepLabel": "透传原样",
-      "codexStrategySelect": "策略选择",
-      "collapseAll": "折叠全部高级配置",
-      "confirmAdd": "确认添加",
-      "confirmAddPending": "添加中...",
-      "confirmUpdate": "确认更新",
-      "confirmUpdatePending": "更新中...",
-      "costMultiplier": "コスト乗数",
-      "costMultiplierDesc": "例:A(コスト1.0x)、C(コスト0.8x)",
-      "costMultiplierLabel": "成本倍率",
-      "costMultiplierPlaceholder": "1.0",
-      "deleteButton": "删除",
-      "enabled": "有効",
-      "expandAll": "展开全部高级配置",
-      "failureThreshold": "失败阈值(次)",
-      "failureThresholdDesc": "连续失败多少次后触发熔断",
-      "failureThresholdPlaceholder": "5",
-      "filterAllProviders": "全部供应商",
-      "filterByType": "タイプでフィルタ",
-      "filterProvider": "筛选供应商类型",
-      "group": "グループ",
-      "groupPlaceholder": "例:premium, economy",
-      "joinClaudePool": "加入 Claude 调度池",
-      "joinClaudePoolDesc": "启用后,此供应商将与 Claude 类型供应商一起参与负载均衡调度",
-      "joinClaudePoolHelp": "仅当模型重定向配置中存在映射到 claude-* 模型时可用。启用后,当用户请求 claude-* 模型时,此供应商也会参与调度选择。",
-      "leaveEmpty": "無制限の場合は空のままにしてください",
-      "limit0Means": "0は無制限を意味します",
-      "limit5hLabel": "5小时消费上限 (USD)",
-      "limitAmount5h": "5時間支出上限(USD)",
-      "limitAmount5hDesc": "例:プロバイダーBが$10制限、$9.8消費済み",
-      "limitAmountMonthly": "月間支出上限(USD)",
-      "limitAmountWeekly": "週間支出上限(USD)",
-      "limitConcurrent": "同時セッション数制限",
-      "limitConcurrentDesc": "例:プロバイダーC制限2、現在アクティブセッション数:2",
-      "limitConcurrentLabel": "并发 Session 上限",
-      "limitMonthlyLabel": "月消费上限 (USD)",
-      "limitPlaceholder0": "0 表示无限制",
-      "limitPlaceholderUnlimited": "留空表示无限制",
-      "limitWeeklyLabel": "周消费上限 (USD)",
-      "modelRedirects": "モデルリダイレクト",
-      "modelRedirectsAddNew": "添加新规则",
-      "modelRedirectsCurrentRules": "当前规则 ({count})",
-      "modelRedirectsDesc": "Claudeモデルリクエストを他のサポートされるモデルにリダイレクトします",
-      "modelRedirectsEmpty": "暂无重定向规则。添加规则后,系统将自动重写请求中的模型名称。",
-      "modelRedirectsExists": "模型 \"{model}\" 已存在重定向规则",
-      "modelRedirectsLabel": "模型重定向配置",
-      "modelRedirectsOptional": "(可选)",
-      "modelRedirectsSourceModel": "用户请求的模型",
-      "modelRedirectsSourcePlaceholder": "例如: claude-sonnet-4-5-20250929",
-      "modelRedirectsSourceRequired": "源模型名称不能为空",
-      "modelRedirectsTargetModel": "实际转发的模型",
-      "modelRedirectsTargetPlaceholder": "例如: glm-4.6",
-      "modelRedirectsTargetRequired": "目标模型名称不能为空",
-      "modelWhitelist": "模型白名单",
-      "modelWhitelistAllowAll": "允许所有 {type} 模型",
-      "modelWhitelistAllowAllClause": "允许所有 Claude 模型",
-      "modelWhitelistAllowAllOpenAI": "允许所有 OpenAI 模型",
-      "modelWhitelistClear": "清空",
-      "modelWhitelistDesc": "限制此供应商可以处理的模型。默认情况下,供应商可以处理该类型下的所有模型。",
-      "modelWhitelistLabel": "允许的模型",
-      "modelWhitelistLoading": "加载中...",
-      "modelWhitelistManualAdd": "手动添加模型",
-      "modelWhitelistManualDesc": "支持添加任意模型名称(不限于价格表中的模型)",
-      "modelWhitelistManualPlaceholder": "输入模型名称(如 gpt-5-turbo)",
-      "modelWhitelistNotFound": "未找到模型",
-      "modelWhitelistSearchPlaceholder": "搜索模型名称...",
-      "modelWhitelistSelectAll": "全选 ({count})",
-      "modelWhitelistSelected": "已选择 {count} 个模型",
-      "modelWhitelistSelectedOnly": "仅允许选中的 {count} 个模型。其他模型的请求不会调度到此供应商。",
-      "name": {
-        "label": "プロバイダー名 *",
-        "placeholder": "例: Zhipu"
-      },
-      "namePlaceholder": "プロバイダー名を入力",
-      "openDuration": "熔断时长(分钟)",
-      "openDurationDesc": "熔断后多久自动进入半开状态",
-      "openDurationPlaceholder": "30",
-      "priority": "優先度",
-      "priorityDesc": "同じ優先度内では、コスト乗数の低い順でソートされます",
-      "priorityLabel": "优先级",
-      "priorityPlaceholder": "0",
-      "providerGroupDesc": "供应商分组标签。只有用户的 providerGroup 与此值匹配时,该用户才能使用此供应商。示例:设置为 \"premium\" 表示只供 providerGroup=\"premium\" 的用户使用",
-      "providerGroupLabel": "供应商分组",
-      "providerGroupPlaceholder": "例如: premium, economy",
-      "providerName": "服务商名称",
-      "providerNamePlaceholder": "例如: 智谱",
-      "providerNameRequired": "服务商名称 *",
-      "providerType": "プロバイダータイプ",
-      "providerTypeDesc": "选择供应商的 API 格式类型。",
-      "providerTypeDisabledNote": "注:Gemini CLI 和 OpenAI Compatible 类型功能正在开发中,暂不可用",
-      "proxy": "プロキシ",
-      "proxyAddressFormats": "支持格式:",
-      "proxyAddressLabel": "代理地址",
-      "proxyAddressOptional": "(可选)",
-      "proxyAddressPlaceholder": "例如: http://proxy.example.com:8080 或 socks5://127.0.0.1:1080",
-      "proxyConfig": "代理配置",
-      "proxyConfigDesc": "配置代理服务器以改善供应商连接性(支持 HTTP、HTTPS、SOCKS4、SOCKS5)",
-      "proxyConfigNone": "未配置",
-      "proxyConfigSummary": "已配置代理",
-      "proxyConfigSummaryFallback": " (启用降级)",
-      "proxyConfigured": "プロキシが設定されています",
-      "proxyFallback": "プロキシ失敗時のフォールバック",
-      "proxyFallbackDesc": "プロキシ失敗時に直接接続にフォールバックします",
-      "proxyFallbackLabel": "代理失败时降级到直连",
-      "proxyNotConfigured": "未設定",
-      "proxyTestButton": "测试连接",
-      "proxyTestDesc": "测试通过配置的代理访问供应商 URL(使用 HEAD 请求,不消耗额度)",
-      "proxyTestFailed": "连接失败",
-      "proxyTestFillUrl": "请先填写供应商 URL",
-      "proxyTestLabel": "连接测试",
-      "proxyTestNetworkError": "网络错误: {error}",
-      "proxyTestProxyError": "代理错误: {error}",
-      "proxyTestResponseTime": "响应时间: {time}",
-      "proxyTestResultConnectionMethod": "连接方式: {via}",
-      "proxyTestResultConnectionMethodDirect": "直连",
-      "proxyTestResultConnectionMethodProxy": "代理",
-      "proxyTestResultErrorType": "错误类型: {type}",
-      "proxyTestResultFailed": "连接失败",
-      "proxyTestResultMessage": "{message}",
-      "proxyTestResultResponseTime": "响应时间: {time}ms",
-      "proxyTestResultStatusCode": "状态码: {code}",
-      "proxyTestResultSuccess": "连接成功 {via}",
-      "proxyTestStatusCode": "| 状态码: {code}",
-      "proxyTestSuccess": "连接成功",
-      "proxyTestTesting": "测试中...",
-      "proxyTestTimeout": "连接超时(5秒)。请检查:\n1. 代理服务器是否可访问\n2. 代理地址和端口是否正确\n3. 代理认证信息是否正确",
-      "proxyTestViaDirect": "(直连)",
-      "proxyTestViaProxy": "(通过代理)",
-      "proxyUrl": "プロキシアドレス",
-      "proxyUrlPlaceholder": "例:http://proxy.example.com:8080 または socks5://127.0.0.1:1080",
-      "rateLimitConfig": "限流配置",
-      "rateLimitConfigNone": "无限制",
-      "rateLimitConfigSummary": "5h: ${fiveHour}, 周: ${weekly}, 月: ${monthly}, 并发: {concurrent}",
-      "remark": "備考",
-      "remarkPlaceholder": "オプション:説明を追加...",
-      "removeRedirect": "リダイレクトを削除",
-      "routingConfig": "路由配置",
-      "routingConfigNone": "未配置",
-      "routingConfigSummary": "{models} 个模型白名单, {redirects} 个重定向",
-      "scheduleParams": "调度参数",
-      "searchClear": "清除搜索",
-      "searchPlaceholder": "プロバイダー名、URL、備考で検索...",
-      "selectProviderType": "プロバイダータイプを選択",
-      "sort": "プロバイダーをソート",
-      "sortByCost": "コスト順",
-      "sortByCreated": "作成日順(新-旧)",
-      "sortByName": "名前順(A-Z)",
-      "sortByPriority": "優先度順(高-低)",
-      "sortByWeight": "重み順(高-低)",
-      "sourceModel": "ソースモデル名",
-      "sourceModelPlaceholder": "例:claude-sonnet-4-5-20250929",
-      "sourceModelRequired": "ソースモデル名は空にできません",
-      "successThreshold": "恢复阈值(次)",
-      "successThresholdDesc": "半开状态下成功多少次后完全恢复",
-      "successThresholdPlaceholder": "2",
-      "targetModel": "ターゲットモデル名",
-      "targetModelPlaceholder": "例:glm-4.6",
-      "targetModelRequired": "ターゲットモデル名は空にできません",
-      "testProxy": "接続をテスト",
-      "testProxyFailed": "プロキシテストに失敗しました",
-      "testProxyFailedError": "接続テスト失敗:",
-      "testProxySuccess": "プロキシ接続成功",
-      "validUrlRequired": "请输入有效的 API 地址",
-      "websiteUrl": {
-        "label": "プロバイダー公式サイト",
-        "placeholder": "https://example.com",
-        "desc": "管理ページへのクイックアクセス用"
-      },
-      "websiteUrlDesc": "供应商官网地址,用于快速跳转管理",
-      "websiteUrlInvalid": "请输入有效的供应商官网地址",
-      "websiteUrlPlaceholder": "https://example.com",
-      "weight": "重み",
-      "weightDesc": "加重ランダム確率。同じ優先度内では、重みが高いほど選択される確率が高くなります。",
-      "weightLabel": "权重",
-      "weightPlaceholder": "1",
-      "title": {
-        "create": "プロバイダーを追加",
-        "edit": "プロバイダーを編集"
-      },
-      "dialogDescription": "プロバイダーの詳細と高度な設定を構成します。",
-      "url": {
-        "label": "API アドレス *",
-        "placeholder": "例: https://open.bigmodel.cn/api/anthropic"
-      },
-      "key": {
-        "label": "API キー",
-        "leaveEmpty": "(空欄のままにすると変更しません)",
-        "placeholder": "API キーを入力",
-        "leaveEmptyDesc": "空欄のままにすると既存のキーを保持します",
-        "currentKey": "現在のキー: {key}"
-      },
-      "buttons": {
-        "expandAll": "高度な設定をすべて展開",
-        "collapseAll": "高度な設定をすべて折りたたむ",
-        "submit": "追加を確定",
-        "submitting": "追加中...",
-        "update": "更新を確定",
-        "updating": "更新中...",
-        "delete": "削除"
-      },
-      "common": {
-        "core": "コア"
-      },
-      "sections": {
-        "routing": {
-          "title": "ルーティング",
-          "summary": {
-            "models": "許可モデル {count} 件",
-            "redirects": "リダイレクト {count} 件",
-            "none": "未設定"
-          },
-          "providerType": {
-            "label": "プロバイダー種別",
-            "desc": "(スケジューリングに影響)",
-            "placeholder": "プロバイダー種別を選択"
-          },
-          "providerTypeDesc": "プロバイダーの API 形式を選択します。",
-          "providerTypeDisabledNote": "注: OpenAI Compatible は開発中のため、現在は使用できません",
-          "modelRedirects": {
-            "label": "モデルリダイレクト設定",
-            "optional": "(任意)"
-          },
-          "joinClaudePool": {
-            "label": "Claude ルーティングプールに参加",
-            "desc": "有効にすると、Claude 系のプロバイダーと共に負荷分散に参加します",
-            "help": "claude-* へのリダイレクトがある場合のみ利用できます。ユーザーが claude-* モデルを要求した際に本プロバイダーも選択対象になります。"
-          },
-          "preserveClientIp": {
-            "label": "クライアント IP を転送",
-            "desc": "x-forwarded-for / x-real-ip を上流に渡します(実際の IP が露出する可能性)",
-            "help": "プライバシー保護のためデフォルトはオフ。上流側で端末 IP が必要な場合のみ有効化してください。"
-          },
-          "modelWhitelist": {
-            "title": "モデル許可リスト",
-            "desc": "このプロバイダーが処理できるモデルを制限します。既定では同タイプのすべてのモデルを処理できます。",
-            "label": "許可するモデル",
-            "optional": "(任意)",
-            "allowAll": "✓ すべてのモデルを許可(推奨)",
-            "selectedOnly": "選択した {count} 件のモデルのみ許可します。他のモデルはこのプロバイダーにルーティングされません。",
-            "moreModels": "+{count} 件 さらに表示"
-          },
-          "scheduleParams": {
-            "title": "スケジューリング設定",
-            "priority": {
-              "label": "優先度",
-              "placeholder": "0",
-              "desc": "値が小さいほど優先度が高くなります(0 が最も高い)。システムは最も高い優先度のプロバイダーのみから選択します。推奨: メイン=0、予備=1、緊急=2"
-            },
-            "weight": {
-              "label": "重み",
-              "placeholder": "1",
-              "desc": "重み付きランダム。同一優先度内では重みが高いほど選ばれる確率が上がります。例 1:2:3 ≈ 16%:33%:50%"
-            },
-            "costMultiplier": {
-              "label": "コスト倍率",
-              "placeholder": "1.0",
-              "desc": "コスト計算の倍率。公式=1.0、20% 安い=0.8、20% 高い=1.2(小数4桁まで)"
-            },
-            "group": {
-              "label": "プロバイダーグループ",
-              "placeholder": "例: premium, economy",
-              "desc": "グループタグ。ユーザーの providerGroup が一致する場合のみ利用可能。例: \"premium\" に設定すると providerGroup=\"premium\" のユーザーのみ対象"
-            }
-          },
-          "cacheTtl": {
-            "label": "キャッシュTTLオーバーライド",
-            "options": {
-              "inherit": "オーバーライドしない(クライアントに従う)",
-              "5m": "5分",
-              "1h": "1時間"
-            },
-            "desc": "プロンプトキャッシュのTTLを強制設定。cache_controlを含むリクエストにのみ適用されます。"
-          },
-          "context1m": {
-            "label": "1M コンテキストウィンドウ",
-            "options": {
-              "inherit": "継承(クライアントに従う)",
-              "forceEnable": "強制有効化",
-              "disabled": "無効"
-            },
-            "desc": "1M コンテキストウィンドウのサポートを設定します。Sonnet モデル(claude-sonnet-4-5、claude-sonnet-4)にのみ適用されます。有効時は段階的料金が適用されます。"
-          },
-          "codexOverrides": {
-            "reasoningEffort": {
-              "label": "推論強度オーバーライド",
-              "help": "回答前にモデルが使う推論の強度(推論トークン量)を制御します。「クライアントに従う」はリクエストを変更しません。その他の値は reasoning.effort を強制します。注意: none は GPT-5.1 のみ、xhigh は GPT-5.1-Codex-Max のみ対応で、未対応モデルではエラーになります。",
-              "options": {
-                "inherit": "オーバーライドしない(クライアントに従う)",
-                "minimal": "minimal",
-                "low": "low",
-                "medium": "medium(デフォルト)",
-                "high": "high",
-                "xhigh": "xhigh(GPT-5.1-Codex-Max のみ)",
-                "none": "none(GPT-5.1 のみ)"
-              }
-            },
-            "reasoningSummary": {
-              "label": "推論サマリーオーバーライド",
-              "help": "推論サマリーを返すかどうかを制御します。auto は簡潔、detailed は詳細です。「クライアントに従う」は reasoning.summary を変更しません。",
-              "options": {
-                "inherit": "オーバーライドしない(クライアントに従う)",
-                "auto": "auto",
-                "detailed": "detailed"
-              }
-            },
-            "textVerbosity": {
-              "label": "出力の詳細度オーバーライド",
-              "help": "モデル出力の冗長さを制御します。low は簡潔、high は詳細です。「クライアントに従う」は text.verbosity を変更しません。",
-              "options": {
-                "inherit": "オーバーライドしない(クライアントに従う)",
-                "low": "low",
-                "medium": "medium(デフォルト)",
-                "high": "high"
-              }
-            },
-            "parallelToolCalls": {
-              "label": "並列ツール呼び出しオーバーライド",
-              "help": "並列の tool calls を許可するかどうかを制御します。「クライアントに従う」は parallel_tool_calls を変更しません。無効化すると並列度が下がる可能性があります。",
-              "options": {
-                "inherit": "オーバーライドしない(クライアントに従う)",
-                "true": "強制有効",
-                "false": "強制無効"
-              }
-            }
-          }
-        },
-        "rateLimit": {
-          "title": "レート制限",
-          "summary": {
-            "fiveHour": "5h: ${amount}",
-            "weekly": "週: ${amount}",
-            "monthly": "月: ${amount}",
-            "total": "総: ${amount}",
-            "concurrent": "同時: {count}",
-            "none": "無制限"
-          },
-          "limit5h": {
-            "label": "5時間の上限 (USD)",
-            "placeholder": "空欄で無制限"
-          },
-          "limitWeekly": {
-            "label": "週の上限 (USD)",
-            "placeholder": "空欄で無制限"
-          },
-          "limitMonthly": {
-            "label": "月の上限 (USD)",
-            "placeholder": "空欄で無制限"
-          },
-          "limitTotal": {
-            "label": "総消費上限 (USD)",
-            "placeholder": "空欄で無制限"
-          },
-          "limitConcurrent": {
-            "label": "同時セッション上限",
-            "placeholder": "0 は無制限"
-          }
-        },
-        "circuitBreaker": {
-          "title": "サーキットブレーカー設定",
-          "summary": "{failureThreshold} 回失敗 / {openDuration} 分間ブレーク / {successThreshold} 回成功で回復 / 各プロバイダー最大 {maxRetryAttempts} 回試行",
-          "desc": "連続失敗時に自動的にブレークして全体の品質を保護します",
-          "failureThreshold": {
-            "label": "失敗しきい値(回)",
-            "placeholder": "5",
-            "desc": "何回連続失敗でブレークするか"
-          },
-          "openDuration": {
-            "label": "ブレーク時間(分)",
-            "placeholder": "30",
-            "desc": "ブレーク後、半開に移行するまでの時間"
-          },
-          "successThreshold": {
-            "label": "回復しきい値(回)",
-            "placeholder": "2",
-            "desc": "半開状態で何回成功したら完全回復するか"
-          },
-          "maxRetryAttempts": {
-            "label": "プロバイダーごとの最大試行回数",
-            "placeholder": "2",
-            "desc": "初回呼び出しを含め、同一プロバイダーで試行する上限。超えると他のプロバイダーへ切り替えます。未入力の場合はデフォルト値を使用。"
-          }
-        },
-        "proxy": {
-          "title": "プロキシ設定",
-          "summary": {
-            "configured": "プロキシ設定済み",
-            "fallback": "(フォールバック有効)",
-            "none": "未設定"
-          },
-          "desc": "プロキシを設定して接続性を改善します(HTTP、HTTPS、SOCKS4、SOCKS5)",
-          "url": {
-            "label": "プロキシ URL",
-            "optional": "(任意)",
-            "placeholder": "例: http://proxy.example.com:8080 または socks5://127.0.0.1:1080",
-            "formats": "対応フォーマット:"
-          },
-          "fallback": {
-            "label": "プロキシ失敗時は直接接続にフォールバック",
-            "desc": "有効にすると、プロキシ接続が失敗した場合に直接接続を試行します"
-          },
-          "test": {
-            "label": "接続テスト",
-            "desc": "設定したプロキシ経由でプロバイダー URL への接続をテストします(HEAD リクエスト、課金なし)"
-          }
-        },
-        "timeout": {
-          "title": "タイムアウト設定",
-          "summary": "初回バイト: {streaming}s | ストリーム間隔: {idle}s | 非ストリーミング: {nonStreaming}s",
-          "desc": "リクエストのタイムアウト時間を設定します。0 は無効を意味します",
-          "streamingFirstByte": {
-            "label": "ストリーミング初バイトタイムアウト(秒)",
-            "placeholder": "30",
-            "desc": "ストリーミングリクエストの初バイトタイムアウト、範囲1~120秒、デフォルト30秒",
-            "core": "true"
-          },
-          "streamingIdle": {
-            "label": "ストリーミングアイドルタイムアウト(秒)",
-            "placeholder": "60",
-            "desc": "ストリーミングリクエストのアイドルタイムアウト、範囲60~600秒、0で無効化(途中停止防止)",
-            "core": "true"
-          },
-          "nonStreamingTotal": {
-            "label": "非ストリーミング総タイムアウト(秒)",
-            "placeholder": "600",
-            "desc": "非ストリーミングリクエストの総タイムアウト、範囲60~1200秒、デフォルト600秒(10分)",
-            "core": "true"
-          },
-          "disableHint": "0に設定するとタイムアウトを無効にします(カナリアロールバックシナリオのみ、非推奨)"
-        },
-        "codexStrategy": {
-          "title": "Codex Instructions ポリシー",
-          "summary": {
-            "auto": "自動(推奨)",
-            "force": "公式を強制",
-            "keep": "そのまま透過"
-          },
-          "desc": "Codex リクエストの instructions フィールドの扱いを制御します。上流ゲートウェイとの互換性に影響します。",
-          "select": {
-            "label": "ポリシー選択",
-            "placeholder": "戦略を選択",
-            "auto": {
-              "label": "自動(推奨)",
-              "desc": "クライアントの instructions を透過し、400 エラー時は公式プロンプトで自動再試行"
-            },
-            "force": {
-              "label": "公式を強制",
-              "desc": "常に公式の Codex CLI instructions を使用(約 4000+ 文字)"
-            },
-            "keep": {
-              "label": "そのまま透過",
-              "desc": "常にクライアントの instructions を透過し、自動再試行しない(緩い中継向け)"
-            }
-          },
-          "hint": "ヒント: 88code や foxcode など一部の厳格な Codex 中継では公式 instructions が必要です。「自動」または「公式を強制」を選択してください。"
-        },
-        "mcpPassthrough": {
-          "title": "MCP パススルー設定",
-          "summary": {
-            "none": "無効",
-            "minimax": "Minimax",
-            "glm": "GLM",
-            "custom": "カスタム (予約)"
-          },
-          "desc": "有効にすると、MCP ツール呼び出しを指定された AI プロバイダにパススルーします(例:minimax の画像認識、Web 検索)",
-          "select": {
-            "label": "パススルータイプ",
-            "none": {
-              "label": "無効",
-              "desc": "MCP パススルーを有効にしません(デフォルト)"
-            },
-            "minimax": {
-              "label": "Minimax",
-              "desc": "minimax MCP サービスにパススルー(画像認識、Web 検索などをサポート)"
-            },
-            "glm": {
-              "label": "GLM",
-              "desc": "GLM MCP サービスにパススルー(画像分析、動画分析などをサポート)"
-            },
-            "custom": {
-              "label": "カスタム",
-              "desc": "カスタム MCP サービスにパススルー(予約、未実装)"
-            },
-            "placeholder": "パススルータイプを選択"
-          },
-          "hint": "ヒント: MCP パススルーにより、Claude Code クライアントは第三者の AI プロバイダー提供のツール機能(画像認識、Web 検索など)を使用できます",
-          "urlLabel": "MCP パススルー URL",
-          "urlPlaceholder": "https://api.minimaxi.com",
-          "urlDesc": "MCP サービスベース URL。空のままにすると、プロバイダー URL から自動的に抽出されます",
-          "urlAuto": "自動抽出: {url}"
-        }
-      },
-      "providerTypes": {
-        "claude": "Claude (Anthropic Messages API)",
-        "claudeAuth": "Claude (Anthropic Auth Token)",
-        "codex": "Codex (Response API)",
-        "gemini": "Gemini (Google Gemini API)",
-        "geminiCli": "Gemini CLI",
-        "geminiCliDisabled": "",
-        "openaiCompatible": "OpenAI Compatible",
-        "openaiCompatibleDisabled": " - 開発中"
-      },
-      "deleteDialog": {
-        "title": "プロバイダーを削除",
-        "description": "プロバイダー「{name}」を削除しますか?この操作は元に戻せません。",
-        "cancel": "キャンセル",
-        "confirm": "削除を確定"
-      },
-      "failureThresholdConfirmDialog": {
-        "title": "特別な設定を確認",
-        "descriptionDisabledPrefix": "サーキットブレーカーの失敗閾値を",
-        "descriptionDisabledValue": "0",
-        "descriptionDisabledMiddle": "に設定しています。これは",
-        "descriptionDisabledAction": "サーキットブレーカーを無効化",
-        "descriptionDisabledSuffix": "することを意味し、プロバイダーは連続した失敗によって遮断されません。",
-        "descriptionHighValuePrefix": "サーキットブレーカーの失敗閾値を",
-        "descriptionHighValueSuffix": "に設定しています。これは高い値であり、プロバイダーが多数の失敗の後にのみ遮断される可能性があります。",
-        "confirmQuestion": "この設定を保存してもよろしいですか?",
-        "cancel": "キャンセル",
-        "confirm": "保存を確定"
-      },
-      "errors": {
-        "invalidUrl": "有効な API アドレスを入力してください",
-        "invalidWebsiteUrl": "有効な公式サイト URL を入力してください",
-        "groupTagTooLong": "プロバイダーグループが長すぎます(合計{max}文字まで)",
-        "addFailed": "プロバイダーの追加に失敗しました",
-        "updateFailed": "プロバイダーの更新に失敗しました",
-        "deleteFailed": "プロバイダーの削除に失敗しました"
-      },
-      "success": {
-        "created": "プロバイダーを追加しました",
-        "createdDesc": "「{name}」を追加しました"
-      }
-    },
-    "guide": {
-      "after": "过滤后:",
-      "before": "过滤前:",
-      "bestPracticesConcurrent": "• 并发控制:根据供应商 API 限制设置 Session 并发数",
-      "bestPracticesCost": "• 成本倍率:官方倍率为 1.0,自建服务可设置为 0.8-1.2",
-      "bestPracticesLimit": "• 限额设置:根据预算设置 5 小时、7 天、30 天限额",
-      "bestPracticesPriority": "• 优先级设置:核心供应商设为 0,备用供应商设为 1-3",
-      "bestPracticesTitle": "最佳实践建议",
-      "bestPracticesWeight": "• 权重配置:根据供应商容量设置权重(容量大 = 权重高)",
-      "circuitBreaker": "サーキットブレーカーチェック",
-      "circuitBreakerOpen": "Aはフィルタされました、残り:B、C、D",
-      "circuitBreakerRecovery": "Aは60秒後に半開状態に自動復帰します",
-      "circuitBreakerRecovery5h": "5時間スライディングウィンドウ後に自動復帰",
-      "costOptimize": "2️⃣ 成本优化:同优先级内,成本倍率低的供应商有更高概率",
-      "costSort": "コストベースのソートフォールバック",
-      "costSortExample": "すべてのプロバイダー:A(default)、B(premium)、C(premium)、D(economy)",
-      "costSortProb": "より安いCがより高い選択確率を持ちます",
-      "costSortResult": "ソート後:C(0.8x)、A(1.0x)",
-      "decision": "决策:",
-      "group": "ユーザーグループフィルタリング",
-      "groupDesc": "ユーザーがプロバイダーグループを指定した場合、システムはそのグループから優先的に選択します",
-      "groupDowngrade": "警告をログに記録し、グローバルプロバイダープールから選択",
-      "groupExample": "ユーザーはproviderGroup = 'premium'を設定しました",
-      "groupFallback": "グループに利用可能なプロバイダーがない場合は、すべてのプロバイダーにフォールバック",
-      "groupFiltered": "AとCのみから選択、BとDはフィルタされます",
-      "groupUnavailable": "ユーザーグループ'vip'のすべてのプロバイダーが無効または制限超過です",
-      "health": "ヘルスフィルタリング(サーキットブレーカー+レート制限)",
-      "healthCheck": "Bが有効で健全かをチェック",
-      "healthCheckAmountLimit": "支出制限超過をチェック(5時間、7日、30日)",
-      "healthCheckAmountLimitExample": "プロバイダーB制限$10(5時間)、$9.8消費済み",
-      "healthCheckCircuit": "プロバイダーA 5回失敗、サーキットブレーカー:オープン",
-      "healthCheckConcurrent": "現在のアクティブセッション数がの制限をチェック",
-      "healthCheckConcurrentExample": "プロバイダーC制限2、現在アクティブ2セッション",
-      "healthFilter": "3️⃣ 健康过滤:自动跳过熔断或超限的供应商",
-      "healthFiltered": "Bはフィルタされました(制限に接近)、残り:C、D",
-      "healthFiltered2": "Cはフィルタされました(満杯)、残り:D",
-      "history": "リクエスト履歴をチェック",
-      "historyDesc": "このAPIキーが過去10秒間に使用したプロバイダーをクエリします",
-      "priority": "優先度階層化",
-      "priorityExample": "異なる優先度を持つ4つのプロバイダーが有効です",
-      "priorityFirst": "1️⃣ 优先级优先:只从最高优先级(数值最小)的供应商中选择",
-      "priorityResult": "最高優先度(0)にフィルタされました:A、C",
-      "priorityStep": "システムは優先度でフィルタし、最高優先度のプロバイダーのみを選択します",
-      "randomResult": "最終的にCがランダムに選択されました",
-      "randomSelect": "加重ランダム",
-      "reset": "サーキットブレーカーを手動リセット",
-      "resetSuccess": "サーキットブレーカーがリセットされました",
-      "scenario1Desc": "系统首先按优先级过滤,只从最高优先级的供应商中选择",
-      "scenario1Step1": "初始状态",
-      "scenario1Step1After": "筛选出最高优先级(0)的供应商:A, C",
-      "scenario1Step1Before": "供应商 A (优先级 0), B (优先级 1), C (优先级 0), D (优先级 2)",
-      "scenario1Step1Decision": "只从 A 和 C 中选择,B 和 D 被过滤",
-      "scenario1Step1Desc": "有 4 个已启用的供应商,优先级各不相同",
-      "scenario1Step2": "成本排序",
-      "scenario1Step2After": "排序后:C (0.8x), A (1.0x)",
-      "scenario1Step2Before": "A (成本 1.0x), C (成本 0.8x)",
-      "scenario1Step2Decision": "成本更低的 C 有更高的被选中概率",
-      "scenario1Step2Desc": "在同优先级内,按成本倍率从低到高排序",
-      "scenario1Step3": "加权随机",
-      "scenario1Step3After": "C 被选中概率 75%, A 被选中概率 25%",
-      "scenario1Step3Before": "C (权重 3), A (权重 1)",
-      "scenario1Step3Decision": "最终随机选择了 C",
-      "scenario1Step3Desc": "使用权重进行随机选择,权重越高被选中概率越大",
-      "scenario1Title": "优先级分层选择",
-      "scenario2Desc": "如果用户指定了供应商组,系统会优先从该组中选择",
-      "scenario2Step1": "检查用户分组",
-      "scenario2Step1After": "过滤出 'premium' 组:B, C",
-      "scenario2Step1Before": "所有供应商:A (default), B (premium), C (premium), D (economy)",
-      "scenario2Step1Decision": "只从 B 和 C 中选择",
-      "scenario2Step1Desc": "用户配置了 providerGroup = 'premium'",
-      "scenario2Step2": "分组降级",
-      "scenario2Step2After": "降级到所有启用的供应商:A, B, C, D",
-      "scenario2Step2Before": "用户组 'vip' 内的供应商全部禁用或超限",
-      "scenario2Step2Decision": "记录警告并从全局供应商池中选择",
-      "scenario2Step2Desc": "如果用户组内没有可用供应商,降级到所有供应商",
-      "scenario2Title": "用户分组过滤",
-      "scenario3Desc": "系统自动过滤掉熔断或超限的供应商",
-      "scenario3Step1": "熔断器检查",
-      "scenario3Step1After": "A 被过滤,剩余:B, C, D",
-      "scenario3Step1Before": "供应商 A 连续失败 5 次,熔断器状态:open",
-      "scenario3Step1Decision": "A 在 60 秒后自动恢复到半开状态",
-      "scenario3Step1Desc": "连续失败 5 次后熔断器打开,60 秒内不可用",
-      "scenario3Step2": "金额限流",
-      "scenario3Step2After": "B 被过滤(接近限额),剩余:C, D",
-      "scenario3Step2Before": "供应商 B 的 5 小时限额 $10,已消耗 $9.8",
-      "scenario3Step2Decision": "5 小时窗口滑动后自动恢复",
-      "scenario3Step2Desc": "检查 5 小时、7 天、30 天的消费额度是否超限",
-      "scenario3Step3": "并发 Session 限制",
-      "scenario3Step3After": "C 被过滤(已满),剩余:D",
-      "scenario3Step3Before": "供应商 C 并发限制 2,当前活跃 Session 数:2",
-      "scenario3Step3Decision": "Session 过期(5 分钟)后自动释放",
-      "scenario3Step3Desc": "检查当前活跃 Session 数是否超过配置的并发限制",
-      "scenario3Title": "健康度过滤(熔断器 + 限流)",
-      "scenario4Desc": "连续对话优先使用同一供应商,利用 Claude 的上下文缓存",
-      "scenario4Step1": "检查历史请求",
-      "scenario4Step1After": "检查 B 是否启用且健康",
-      "scenario4Step1Before": "最近一次请求使用了供应商 B",
-      "scenario4Step1Decision": "B 可用,直接复用,跳过随机选择",
-      "scenario4Step1Desc": "查询该 API Key 最近 10 秒内使用的供应商",
-      "scenario4Step2": "复用失效",
-      "scenario4Step2After": "进入正常选择流程",
-      "scenario4Step2Before": "上次使用的供应商 B 已被禁用或熔断",
-      "scenario4Step2Decision": "从其他可用供应商中选择",
-      "scenario4Step2Desc": "如果上次使用的供应商不可用,则重新选择",
-      "scenario4Title": "会话复用机制",
-      "scenariosTitle": "交互式场景演示",
-      "session": "セッション再利用メカニズム",
-      "sessionDesc": "前回使用したプロバイダーが利用できない場合は再選択します",
-      "sessionExample": "最後のリクエストはプロバイダーBを使用しました",
-      "sessionExpired": "セッションは期限切れ後に自動的に解放されます(5分)",
-      "sessionFallback": "他の利用可能なプロバイダーから選択",
-      "sessionLastUsed": "Bは利用可能、直接再利用、ランダム選択をスキップ",
-      "sessionReuse": "4️⃣ 会话复用:连续对话复用同一供应商,节省上下文成本",
-      "sessionUnavailable": "前回使用したプロバイダーBは無効またはサーキットオープン状態です",
-      "step": "步骤",
-      "title": "核心原则",
-      "weight": "重みに基づく加重ランダム選択",
-      "weightCalc": "Cは75%の選択確率、Aは25%",
-      "weightExample": "C(重み3)、A(重み1)"
-    },
-    "keyLoading": "加载中...",
-    "noProviders": "暂无服务商配置",
-    "noProvidersDesc": "添加你的第一个 API 服务商",
-    "notFound": "プロバイダーが見つかりません",
-    "official": "官网",
-    "resetCircuit": "熔断器已重置",
-    "resetCircuitDesc": "供应商 \"{name}\" 的熔断状态已解除",
-    "resetCircuitFailed": "重置熔断器失败",
-    "scheduling": "スケジューリング戦略の詳細説明",
-    "schedulingDesc": "プロバイダー選択の仕組み:優先度階層化、セッション再利用、ロードバランシング、フェイルオーバーを理解します",
-    "searchNoResults": "未找到匹配的供应商",
-    "searchResults": "找到 {count} 个匹配的供应商",
-    "section": {
-      "description": "配置上游服务商的金额限流和并发限制,留空表示无限制。",
-      "leaderboard": "プロバイダーランキング",
-      "title": "服务商管理"
-    },
-    "filter": {
-      "status": {
-        "all": "すべてのステータス",
-        "active": "有効",
-        "inactive": "無効"
-      },
-      "groups": {
-        "label": "グループ:",
-        "all": "すべて",
-        "default": "default"
-      },
-      "circuitBroken": "サーキットブレーカー"
-    },
-    "subtitle": "プロバイダー管理",
-    "subtitleDesc": "上流プロバイダーの支出制限とセッション並行制限を設定します。空のままにすると無制限です。",
-    "title": "プロバイダー管理",
-    "todayUsage": "今日用量",
-    "todayUsageCount": "{count} 次",
-    "toggleFailed": "状态切换失败",
-    "toggleSuccess": "供应商已{status}",
-    "toggleSuccessDesc": "供应商 \"{name}\" 状态已更新",
-    "updateFailed": "更新服务商失败",
-    "viewKey": "查看完整 API Key",
-    "viewKeyDesc": "请妥善保管,不要泄露给他人",
-    "types": {
-      "claude": {
-        "label": "Claude",
-        "description": "Anthropic 公式 API"
-      },
-      "claudeAuth": {
-        "label": "Claude Auth",
-        "description": "Claude リレーサービス"
-      },
-      "codex": {
-        "label": "Codex",
-        "description": "Codex CLI API"
-      },
-      "gemini": {
-        "label": "Gemini",
-        "description": "Google Gemini API"
-      },
-      "geminiCli": {
-        "label": "Gemini CLI",
-        "description": "Gemini CLI API"
-      },
-      "openaiCompatible": {
-        "label": "OpenAI Compatible",
-        "description": "OpenAI 互換 API"
-      }
-    },
-    "list": {
-      "priority": "優先度",
-      "weight": "重み",
-      "costMultiplier": "コスト倍率",
-      "todayUsageLabel": "本日の使用量",
-      "todayUsageCount": "{count} 回",
-      "circuitBroken": "遮断中",
-      "officialWebsite": "公式",
-      "viewFullKey": "完全な API キーを表示",
-      "viewFullKeyDesc": "安全に保管し、他人と共有しないでください",
-      "keyLoading": "読み込み中...",
-      "confirmDeleteTitle": "プロバイダーの削除を確認しますか?",
-      "confirmDeleteMessage": "プロバイダー \"{name}\" を削除してもよろしいですか?この操作は元に戻せません。",
-      "deleteButton": "削除",
-      "cancelButton": "キャンセル",
-      "deleteSuccess": "削除に成功しました",
-      "deleteSuccessDesc": "プロバイダー \"{name}\" が削除されました",
-      "deleteFailed": "削除に失敗しました",
-      "deleteError": "操作中にエラーが発生しました",
-      "unknownError": "不明なエラー",
-      "getKeyFailed": "キーの取得に失敗しました",
-      "keyCopied": "キーがクリップボードにコピーされました",
-      "copyFailed": "コピーに失敗しました",
-      "clipboardUnavailable": "この環境ではクリップボードを使用できません。手動でコピーしてください。",
-      "resetCircuitSuccess": "サーキットブレーカーがリセットされました",
-      "resetCircuitSuccessDesc": "プロバイダー \"{name}\" のサーキットブレーカーステータスがクリアされました",
-      "resetCircuitFailed": "サーキットブレーカーのリセットに失敗しました",
-      "resetUsageTitle": "総用量をリセット",
-      "resetUsageSuccess": "総用量をリセットしました",
-      "resetUsageSuccessDesc": "プロバイダー \"{name}\" の総用量をリセットしました",
-      "resetUsageFailed": "総用量のリセットに失敗しました",
-      "toggleSuccess": "プロバイダーが{status}になりました",
-      "toggleSuccessDesc": "プロバイダー \"{name}\" のステータスが更新されました",
-      "toggleFailed": "切り替えに失敗しました",
-      "statusEnabled": "有効",
-      "statusDisabled": "無効"
-    },
-    "inlineEdit": {
-      "save": "保存",
-      "cancel": "キャンセル",
-      "saveSuccess": "保存に成功しました",
-      "saveFailed": "保存に失敗しました",
-      "priorityLabel": "優先度",
-      "weightLabel": "重み",
-      "costMultiplierLabel": "コスト倍率",
-      "priorityInvalid": "0 以上の整数を入力してください",
-      "weightInvalid": "1〜100 の整数を入力してください",
-      "costMultiplierInvalid": "0以上の数値を入力してください"
-    },
-    "schedulingDialog": {
-      "title": "プロバイダースケジューリングルール",
-      "description": "システムが高可用性とコスト最適化のために上流プロバイダーをインテリジェントに選択する方法を理解する",
-      "triggerButton": "スケジューリングルール",
-      "step": "ステップ",
-      "before": "前:",
-      "after": "後:",
-      "decision": "決定:"
-    },
-    "sort": {
-      "byName": "名前順 (A-Z)",
-      "byPriority": "優先度順 (高-低)",
-      "byWeight": "重み順 (高-低)",
-      "byActualPriority": "実際の選択優先順",
-      "byCreatedAt": "作成日時順 (新-旧)",
-      "placeholder": "プロバイダーを並べ替え"
-    },
-    "search": {
-      "placeholder": "プロバイダー名、URL、メモを検索...",
-      "clear": "検索をクリア",
-      "found": "{count}件のプロバイダーが見つかりました",
-      "notFound": "一致するプロバイダーが見つかりません",
-      "showing": "{filtered} / {total} プロバイダーを表示"
-    }
-  },
-  "sensitiveWords": {
-    "add": "センシティブワードを追加",
-    "addFailed": "センシティブワードの作成に失敗しました",
-    "addSuccess": "センシティブワードが正常に作成されました",
-    "cacheStats": "キャッシュ統計:部分一致({containsCount}) 完全一致({exactCount}) 正規表現({regexCount})",
-    "confirmDelete": "センシティブワード「{word}」を削除してもよろしいですか?",
-    "delete": "センシティブワードを削除",
-    "deleteFailed": "削除に失敗しました",
-    "deleteSuccess": "センシティブワードが正常に削除されました",
-    "description": "センシティブコンテンツをブロックするためにセンシティブワードフィルタリングルールを設定します。",
-    "dialog": {
-      "addDescription": "センシティブワードフィルタリングルールを設定します。マッチしたリクエストはアップストリームに転送されません。",
-      "addTitle": "センシティブワードを追加",
-      "creating": "作成中...",
-      "descriptionLabel": "説明",
-      "descriptionPlaceholder": "オプション:説明を追加...",
-      "editDescription": "センシティブワード設定を変更します。変更後、自動的にキャッシュがリフレッシュされます。",
-      "editTitle": "センシティブワードを編集",
-      "matchTypeContains": "部分一致 - テキストにこの単語が含まれている場合ブロック",
-      "matchTypeExact": "完全一致 - 完全に一致する場合のみブロック",
-      "matchTypeLabel": "マッチタイプ *",
-      "matchTypeRegex": "正規表現 - 複雑なパターンマッチングをサポート",
-      "saving": "保存中...",
-      "wordLabel": "センシティブワード *",
-      "wordPlaceholder": "センシティブワードを入力...",
-      "wordRequired": "センシティブワードを入力してください"
-    },
-    "disable": "センシティブワードが無効になりました",
-    "edit": "センシティブワードを編集",
-    "editFailed": "センシティブワードの更新に失敗しました",
-    "editSuccess": "センシティブワードが正常に更新されました",
-    "emptyState": "センシティブワードがありません。右上の「センシティブワードを追加」をクリックして設定を開始してください。",
-    "enable": "センシティブワードが有効になりました",
-    "refreshCache": "キャッシュを更新",
-    "refreshCacheFailed": "キャッシュのリフレッシュに失敗しました",
-    "refreshCacheSuccess": "キャッシュのリフレッシュに成功しました。{count}個のセンシティブワードを読み込みました",
-    "section": {
-      "description": "センシティブワードによってブロックされたリクエストはアップストリームに転送されず、課金もされません。部分一致、完全一致、正規表現の3つのモードをサポートしています。",
-      "title": "センシティブワードリスト"
-    },
-    "table": {
-      "actions": "操作",
-      "createdAt": "作成日時",
-      "description": "説明",
-      "matchType": "マッチタイプ",
-      "matchTypeContains": "部分一致",
-      "matchTypeExact": "完全一致",
-      "matchTypeRegex": "正規表現",
-      "status": "ステータス",
-      "word": "センシティブワード"
-    },
-    "title": "センシティブワード管理",
-    "toggleFailed": "トグルに失敗しました",
-    "toggleFailedError": "トグルに失敗しました:"
-  },
-  "requestFilters": {
-    "nav": "リクエストフィルター",
-    "title": "リクエストフィルター",
-    "description": "上流に送る前にヘッダー削除/上書きやボディ置換を行い、リクエストをサニタイズします。",
-    "add": "フィルター追加",
-    "addSuccess": "作成しました",
-    "addFailed": "作成に失敗しました",
-    "edit": "フィルター編集",
-    "editSuccess": "更新しました",
-    "editFailed": "更新に失敗しました",
-    "delete": "フィルター削除",
-    "deleteSuccess": "削除しました",
-    "deleteFailed": "削除に失敗しました",
-    "enable": "有効",
-    "disable": "無効",
-    "confirmDelete": "フィルター \"{name}\" を削除しますか?",
-    "empty": "フィルターがありません。追加してください。",
-    "refreshCache": "キャッシュ更新",
-    "refreshSuccess": "{count} 件読み込みました",
-    "refreshFailed": "更新に失敗しました",
-    "dialog": {
-      "createTitle": "フィルター追加",
-      "editTitle": "フィルター編集",
-      "name": "名称",
-      "scope": "スコープ",
-      "action": "アクション",
-      "target": "対象フィールド/パス",
-      "replacement": "置換値 (任意)",
-      "description": "説明 (任意)",
-      "priority": "優先度",
-      "matchType": "マッチタイプ",
-      "matchTypeContains": "含む",
-      "matchTypeExact": "完全一致",
-      "matchTypeRegex": "正規表現",
-      "jsonPathPlaceholder": "例: messages.0.content / data.items[0].token",
-      "targetPlaceholder": "ヘッダー名またはテキスト/パス",
-      "replacementPlaceholder": "文字列またはJSON。空でクリア",
-      "save": "保存",
-      "saving": "保存中...",
-      "validation": {
-        "fieldRequired": "名称と対象は必須です"
-      },
-      "bindingType": "適用先",
-      "bindingGlobal": "全プロバイダー(グローバル)",
-      "bindingProviders": "特定のプロバイダー",
-      "bindingGroups": "プロバイダーグループ",
-      "selectProviders": "プロバイダーを選択...",
-      "selectGroups": "グループを選択...",
-      "searchProviders": "プロバイダー検索...",
-      "searchGroups": "グループ検索...",
-      "noProvidersFound": "プロバイダーが見つかりません",
-      "noGroupsFound": "グループが見つかりません",
-      "providersSelected": "{count}件のプロバイダーを選択",
-      "groupsSelected": "{count}件のグループを選択",
-      "loading": "読み込み中...",
-      "clear": "クリア",
-      "selectAll": "すべて選択"
-    },
-    "table": {
-      "name": "名称",
-      "scope": "スコープ",
-      "action": "アクション",
-      "target": "対象",
-      "replacement": "置換値",
-      "priority": "優先度",
-      "apply": "適用",
-      "status": "状態",
-      "createdAt": "作成日時",
-      "actions": "操作"
-    },
-    "scopeLabel": {
-      "header": "Header",
-      "body": "Body"
-    },
-    "actionLabel": {
-      "remove": "ヘッダー削除",
-      "set": "ヘッダー設定",
-      "json_path": "JSONパス置換",
-      "text_replace": "テキスト置換"
-    },
-    "applyToAll": "すべてのリクエストに適用",
-    "providers": "プロバイダー",
-    "groups": "グループ"
-  },
-  "errorRules": {
-    "nav": "エラールール",
-    "title": "エラールール管理",
-    "description": "自動再試行を行わないクライアントエラールールを管理します。設定後、ルールに一致するエラーは再試行せずユーザーに直接返され、プロバイダーのサーキットブレーカーにもカウントされません。",
-    "section": {
-      "title": "エラールールリスト"
-    },
-    "tester": {
-      "title": "エラールールテスト",
-      "description": "エラーメッセージを入力して、設定済みルールに一致するかと最終的な返却内容を確認します。",
-      "inputLabel": "テストするエラーメッセージ",
-      "inputPlaceholder": "検証したいエラーメッセージを入力...",
-      "testButton": "テストを実行",
-      "testing": "テスト中...",
-      "matched": "エラールールに一致しました",
-      "notMatched": "一致するルールなし",
-      "finalResponse": "オーバーライドレスポンス",
-      "ruleInfo": "一致したルール",
-      "noRule": "一致したルールはありません",
-      "category": "カテゴリ",
-      "pattern": "パターン",
-      "matchType": "マッチタイプ",
-      "overrideStatusCode": "オーバーライドステータスコード",
-      "testFailed": "テストに失敗しました。再度お試しください",
-      "messageRequired": "テストするエラーメッセージを入力してください",
-      "warnings": "設定の警告",
-      "statusCodeOnlyOverride": "ステータスコードのみオーバーライドされ、レスポンスボディはアップストリームのエラーが使用されます"
-    },
-    "add": "エラールールを追加",
-    "addSuccess": "エラールールが正常に作成されました",
-    "addFailed": "エラールールの作成に失敗しました",
-    "edit": "エラールールを編集",
-    "editSuccess": "エラールールが正常に更新されました",
-    "editFailed": "エラールールの更新に失敗しました",
-    "delete": "エラールールを削除",
-    "deleteSuccess": "エラールールが正常に削除されました",
-    "deleteFailed": "削除に失敗しました",
-    "enable": "エラールールが有効になりました",
-    "disable": "エラールールが無効になりました",
-    "toggleFailed": "切り替えに失敗しました",
-    "toggleFailedError": "切り替えに失敗しました:",
-    "refreshCache": "ルールを同期",
-    "refreshCacheSuccess": "ルールが正常に同期され、{count} 個のエラールールがロードされました",
-    "refreshCacheFailed": "ルールの同期に失敗しました",
-    "cacheStats": "キャッシュ: {totalCount}件のルール",
-    "emptyState": "エラールールがまだありません。右上の「エラールールを追加」をクリックして設定を開始してください。",
-    "confirmDelete": "エラールール \"{pattern}\" を削除してもよろしいですか?",
-    "dialog": {
-      "addTitle": "エラールールを追加",
-      "addDescription": "エラーメッセージの正規表現パターンを設定します。マッチしたエラーはリトライ不可能なクライアントエラーとして識別されます。",
-      "editTitle": "エラールールを編集",
-      "editDescription": "エラールール設定を変更します。変更後、キャッシュが自動的に更新されます。",
-      "patternLabel": "正規表現パターン *",
-      "patternPlaceholder": "正規表現を入力...",
-      "patternRequired": "正規表現パターンを入力してください",
-      "patternHint": "JavaScript正規表現構文をサポート、例:prompt is too long|invalid.*request",
-      "categoryLabel": "ルールカテゴリ *",
-      "categoryPlaceholder": "ルールカテゴリを選択",
-      "categoryRequired": "ルールカテゴリを選択してください",
-      "categoryHint": "分類管理と統計のためのエラーカテゴリを選択",
-      "descriptionLabel": "説明",
-      "descriptionPlaceholder": "オプション: 説明を追加...",
-      "invalidRegex": "正規表現の構文エラー",
-      "regexTester": "正規表現テスター",
-      "testMessageLabel": "テストメッセージ",
-      "testMessagePlaceholder": "テストするエラーメッセージを入力...",
-      "matchSuccess": "マッチ成功",
-      "matchFailed": "マッチなし",
-      "invalidPattern": "無効な正規表現",
-      "matchedText": "マッチしたテキスト",
-      "defaultRuleHint": "デフォルトルールのパターンは変更できません",
-      "enableOverride": "エラーオーバーライドを有効にする",
-      "enableOverrideHint": "有効にすると、クライアントに返すエラーレスポンスとステータスコードをカスタマイズできます。元のエラーはデータベースに記録されます。現在、Claude APIエラー形式のみサポートしています。",
-      "overrideResponseLabel": "オーバーライドレスポンス(JSON形式)",
-      "overrideResponsePlaceholder": "{\n  \"type\": \"error\",\n  \"error\": {\n    \"type\": \"invalid_request_error\",\n    \"message\": \"カスタムメッセージ\"\n  }\n}",
-      "overrideResponseHint": "空白のままにするとステータスコードのみオーバーライドします。",
-      "overrideStatusCodeLabel": "オーバーライドステータスコード(オプション)",
-      "overrideStatusCodePlaceholder": "例: 400",
-      "overrideStatusCodeHint": "空白のままにするとアップストリームのステータスコードを使用します。範囲: 400-599。",
-      "useTemplate": "Claude Error テンプレート",
-      "useTemplateConfirm": "入力済みの内容をテンプレートで上書きしますか?",
-      "validJson": "JSON 形式は有効です",
-      "invalidJson": "JSON形式が無効です",
-      "invalidStatusCode": "ステータスコードは400-599の範囲内でなければなりません",
-      "creating": "作成中...",
-      "saving": "保存中..."
-    },
-    "table": {
-      "pattern": "正規表現パターン",
-      "category": "ルールカテゴリ",
-      "description": "説明",
-      "status": "ステータス",
-      "default": "デフォルト",
-      "isEnabled": "有効状態",
-      "isDefault": "デフォルトルール",
-      "createdAt": "作成日時",
-      "actions": "操作"
-    },
-    "form": {
-      "fields": {
-        "pattern": "正規表現パターン",
-        "category": "ルールカテゴリ",
-        "description": "説明"
-      },
-      "placeholders": {
-        "pattern": "例: prompt is too long",
-        "category": "カテゴリを選択",
-        "description": "オプション: 説明を追加..."
-      },
-      "labels": {
-        "pattern": "正規表現パターン *",
-        "category": "ルールカテゴリ *",
-        "description": "説明",
-        "isEnabled": "有効状態"
-      }
-    },
-    "actions": {
-      "add": "追加",
-      "edit": "編集",
-      "delete": "削除",
-      "refresh": "更新",
-      "test": "テスト",
-      "messages": {
-        "success": "操作が成功しました",
-        "error": "操作が失敗しました"
-      }
-    },
-    "validation": {
-      "patternRequired": "正規表現パターンを入力してください",
-      "categoryRequired": "ルールカテゴリを選択してください",
-      "patternInvalid": "正規表現の構文エラー",
-      "redosRisk": "正規表現に ReDoS リスクがあります。パターンを簡略化してください",
-      "patternTooComplex": "正規表現が複雑すぎます"
-    },
-    "categories": {
-      "prompt_limit": "プロンプト長制限",
-      "content_filter": "コンテンツフィルター",
-      "pdf_limit": "PDF ページ制限",
-      "thinking_error": "Thinking フォーマットエラー",
-      "parameter_error": "パラメータ検証失敗",
-      "invalid_request": "無効なリクエスト",
-      "cache_limit": "キャッシュ制御制限"
-    },
-    "regexTester": {
-      "title": "正規表現テスター",
-      "testMessage": "テストメッセージ",
-      "testMessagePlaceholder": "テストするエラーメッセージを入力...",
-      "matchResult": "マッチ結果",
-      "matched": "マッチしました",
-      "notMatched": "マッチしませんでした",
-      "test": "テスト"
-    },
-    "defaultRules": {
-      "cannotDelete": "デフォルトルールは削除できません",
-      "cannotDisable": "デフォルトルールは有効のままにすることをお勧めします"
-    }
-  },
-  "mcpPassthroughConfig": "MCP パススルー設定",
-  "mcpPassthroughConfigNone": "無効",
-  "mcpPassthroughConfigMinimax": "Minimax",
-  "mcpPassthroughConfigGlm": "GLM",
-  "mcpPassthroughConfigCustom": "カスタム (予約)",
-  "mcpPassthroughDesc": "有効にすると、MCP ツール呼び出しを指定された AI プロバイダにパススルーします(例:minimax の画像認識、Web 検索)",
-  "mcpPassthroughSelect": "パススルータイプ",
-  "mcpPassthroughNoneLabel": "無効",
-  "mcpPassthroughNoneDesc": "MCP パススルーを有効にしません(デフォルト)",
-  "mcpPassthroughMinimaxLabel": "Minimax",
-  "mcpPassthroughMinimaxDesc": "minimax MCP サービスにパススルー(画像認識、Web 検索などをサポート)",
-  "mcpPassthroughGlmLabel": "GLM",
-  "mcpPassthroughGlmDesc": "GLM MCP サービスにパススルー(画像分析、動画分析などをサポート)",
-  "mcpPassthroughCustomLabel": "カスタム",
-  "mcpPassthroughCustomDesc": "カスタム MCP サービスにパススルー(予約、未実装)",
-  "mcpPassthroughHint": "ヒント: MCP パススルーにより、Claude Code クライアントは第三者の AI プロバイダ提供的ツール機能(画像認識、Web 検索など)を使用できます",
-  "mcpPassthroughUrlLabel": "MCP パススルー URL",
-  "mcpPassthroughUrlPlaceholder": "https://api.minimaxi.com",
-  "mcpPassthroughUrlDesc": "MCP サービスベース URL。空のままにすると、プロバイダ URL から自動的に抽出されます",
-  "mcpPassthroughUrlAuto": "自動抽出: {url}"
-}

+ 51 - 0
messages/ja/settings/clientVersions.json

@@ -0,0 +1,51 @@
+{
+  "description": "クライアントバージョン要件を管理し、ユーザーが最新の安定版を使用していることを確認します。VSCodeとCLIは個別に管理されます。",
+  "empty": {
+    "description": "過去7日間に認識可能なクライアントを使用したアクティブユーザーがいません",
+    "title": "クライアントデータなし"
+  },
+  "features": {
+    "activeWindow": "アクティブウィンドウ:",
+    "activeWindowDesc": "過去7日間にリクエストがあったユーザーのみを集計",
+    "autoDetect": "システムは各クライアントの最新安定版(GAバージョン)を自動検出します",
+    "blockOldVersion": "旧バージョンを使用するユーザーはHTTP 400エラーを受信し、サービスを継続使用できません",
+    "errorMessage": "エラーメッセージには現在のバージョンとアップグレード必要バージョン番号が含まれます",
+    "gaRule": "判定ルール:",
+    "gaRuleDesc": "1人以上のユーザーが使用しているバージョンをGAバージョンとみなします",
+    "recommendation": "推奨方法:",
+    "recommendationDesc": "まず下記のバージョン分布を確認し、新バージョンが安定していることを確認してから有効にしてください。",
+    "title": "機能説明",
+    "whatHappens": "有効化後の動作:"
+  },
+  "section": {
+    "distribution": {
+      "description": "過去7日間のアクティブユーザーのクライアントバージョン情報を表示します。各クライアントタイプごとにGAバージョンを独立して集計します。",
+      "title": "クライアントバージョン分布"
+    },
+    "settings": {
+      "description": "有効にすると、システムはクライアントバージョンを自動的に検出し、旧バージョンユーザーのリクエストをブロックします。",
+      "title": "アップグレードリマインダー設定"
+    }
+  },
+  "table": {
+    "currentGA": "現在のGAバージョン:",
+    "internalType": "内部タイプ:",
+    "lastActive": "最終アクティブ時間",
+    "latest": "最新版",
+    "needsUpgrade": "アップグレード必要",
+    "noUsers": "ユーザーデータなし",
+    "status": "ステータス",
+    "unknown": "不明",
+    "user": "ユーザー",
+    "usersCount": "{count}名のユーザー",
+    "version": "現在のバージョン"
+  },
+  "title": "クライアント更新リマインダー",
+  "toggle": {
+    "description": "有効にすると、システムはクライアントバージョンを自動的に検出し、古いバージョンをブロックします。",
+    "disableSuccess": "クライアントバージョンチェックが無効になりました",
+    "enable": "クライアントバージョンチェックを有効にする",
+    "enableSuccess": "クライアントバージョンチェックが有効になりました",
+    "toggleFailed": "トグルに失敗しました"
+  }
+}

+ 31 - 0
messages/ja/settings/common.json

@@ -0,0 +1,31 @@
+{
+  "cancel": "キャンセル",
+  "completed": "完了",
+  "confirm": "確認",
+  "copied": "キーをクリップボードにコピーしました",
+  "copy": "コピー",
+  "copyFailed": "コピーに失敗しました",
+  "create": "作成",
+  "creating": "作成中...",
+  "delete": "削除",
+  "disabled": "無効",
+  "edit": "編集",
+  "empty": "結果が見つかりません",
+  "enabled": "有効",
+  "error": "不明なエラー",
+  "failed": "失敗",
+  "loading": "読み込み中...",
+  "none": "なし(このバージョンを使用しているユーザーなし)",
+  "refresh": "更新",
+  "reset": "リセット",
+  "save": "保存する",
+  "saving": "保存しています...",
+  "submit": "送信",
+  "success": "成功しました",
+  "test": "テスト",
+  "testing": "テスト中...",
+  "unlimited": "無制限",
+  "unlimited_desc": "無制限",
+  "update": "更新する",
+  "updating": "更新しています..."
+}

+ 89 - 0
messages/ja/settings/config.json

@@ -0,0 +1,89 @@
+{
+  "autoCleanup": "ログ自動クリーンアップ",
+  "autoCleanupDesc": "スケジュールに従って履歴ログを自動的にクリーンアップし、データベース容量を解放します。",
+  "description": "システムの基本パラメータを管理し、サイト表示と統計動作に影響します。",
+  "form": {
+    "allowGlobalView": "グローバル使用量表示を許可",
+    "allowGlobalViewDesc": "無効にすると、一般ユーザーはダッシュボードで自分のキーの使用統計のみを表示できます。",
+    "autoCleanupSaved": "自動クリーンアップ設定が保存されました",
+    "billingModelSource": "課金モデルソース",
+    "billingModelSourceDesc": "モデルリダイレクト時に課金に使用するモデルを設定します。「リダイレクト前」はユーザーがリクエストした元のモデル、「リダイレクト後」は実際に呼び出されたモデルを使用します。",
+    "billingModelSourceOptions": {
+      "original": "リダイレクト前(元のモデル)",
+      "redirected": "リダイレクト後(実際のモデル)"
+    },
+    "billingModelSourcePlaceholder": "課金モデルソースを選択",
+    "cleanupBatchSize": "バッチサイズ",
+    "cleanupBatchSizeDesc": "バッチごとに削除するレコード数(範囲:1000-100000、推奨10000)",
+    "cleanupBatchSizePlaceholder": "10000",
+    "cleanupBatchSizeRequired": "バッチサイズ *",
+    "cleanupRetentionDays": "保持日数",
+    "cleanupRetentionDaysDesc": "この日数を超えるログは自動的にクリーンアップされます(範囲:1-365日)",
+    "cleanupRetentionDaysPlaceholder": "30",
+    "cleanupRetentionDaysRequired": "保持日数 *",
+    "cleanupSchedule": "クリーンアップスケジュール",
+    "cleanupScheduleCronDesc": "Cron式、デフォルト:0 2 * * *(毎日午前2時)",
+    "cleanupScheduleCronExample": "例:0 3 * * 0(毎週日曜日午前3時)",
+    "cleanupScheduleDesc": "自動クリーンアップの実行スケジュールを選択します",
+    "cleanupScheduleLabel": "実行時間(Cron)",
+    "cleanupSchedulePlaceholder": "0 2 * * *",
+    "cleanupScheduleRequired": "実行時間(Cron)*",
+    "configUpdated": "システム設定が更新されました。ページが更新され、通貨表示の変更が適用されます。",
+    "currencies": {
+      "CNY": "¥ 人民元 (CNY)",
+      "EUR": "€ ユーロ (EUR)",
+      "GBP": "£ 英ポンド (GBP)",
+      "HKD": "HK$ 香港ドル (HKD)",
+      "JPY": "¥ 日本円 (JPY)",
+      "KRW": "₩ 韓国ウォン (KRW)",
+      "SGD": "S$ シンガポールドル (SGD)",
+      "TWD": "NT$ 新台湾ドル (TWD)",
+      "USD": "$ 米ドル (USD)"
+    },
+    "currencyDisplay": "通貨表示単位",
+    "currencyDisplayDesc": "変更後、システムのすべてのページとAPIインターフェースは対応する通貨記号を使用します(記号のみ、為替レート変換なし)。",
+    "currencyDisplayPlaceholder": "通貨単位を選択",
+    "enableAutoCleanup": "自動クリーンアップを有効にする",
+    "enableAutoCleanupDesc": "スケジュールに従って履歴ログを自動的にクリーンアップします",
+    "enableHttp2": "HTTP/2 を有効にする",
+    "enableHttp2Desc": "有効にすると、プロキシ要求は優先的に HTTP/2 を使用します。HTTP/2 が失敗した場合は自動的に HTTP/1.1 にフォールバックします。",
+    "enableResponseFixer": "レスポンス整流を有効化",
+    "enableResponseFixerDesc": "上流応答の一般的な形式問題(エンコーディング、SSE、途切れた JSON)を自動修復します(既定で有効)。",
+    "enableThinkingSignatureRectifier": "thinking 署名整流を有効化",
+    "enableThinkingSignatureRectifierDesc": "Anthropic プロバイダーで thinking 署名の不整合や不正なリクエストエラーが発生した場合、thinking 関連ブロックを削除して同一プロバイダーへ1回だけ再試行します(既定で有効)。",
+    "interceptAnthropicWarmupRequests": "Warmup リクエストを遮断(Anthropic)",
+    "interceptAnthropicWarmupRequestsDesc": "有効にすると、Claude Code の Warmup プローブ要求は CCH が直接短い応答を返し、上流プロバイダーへのリクエストを回避します。ログには残りますが、課金/レート制限/統計には含まれません。",
+    "keepDays": "保持日数",
+    "keepDaysDesc": "指定した日数より古いログをクリーンアップします",
+    "responseFixerFixEncoding": "エンコーディングを修復",
+    "responseFixerFixEncodingDesc": "BOM/NULL バイトを除去し、無効な UTF-8 を正規化します。",
+    "responseFixerFixSseFormat": "SSE 形式を修復",
+    "responseFixerFixSseFormatDesc": "不足している data: 前置きを補い、改行を正規化し、よくあるフィールド形式を修正します。",
+    "responseFixerFixTruncatedJson": "途切れた JSON を修復",
+    "responseFixerFixTruncatedJsonDesc": "未閉じの括弧/引用符を補い、末尾カンマを除去し、必要に応じて null を補完します。",
+    "saveConfig": "設定を保存",
+    "saveError": "保存に失敗しました",
+    "saveFailed": "保存に失敗しました",
+    "saveSettings": "設定を保存",
+    "saveSuccess": "正常に保存されました",
+    "siteTitle": "サイトタイトル",
+    "siteTitleDesc": "ブラウザタブのタイトルとシステムのデフォルト表示名を設定するために使用されます。",
+    "siteTitlePlaceholder": "例:Claude Code Hub",
+    "siteTitleRequired": "サイトタイトルは空にできません",
+    "verboseProviderError": "詳細なプロバイダーエラー",
+    "verboseProviderErrorDesc": "有効にすると、すべてのプロバイダーが利用不可の場合に詳細なエラーメッセージ(プロバイダー数、レート制限の理由など)を返します。無効の場合は簡潔なエラーコードのみを返します。"
+  },
+  "section": {
+    "autoCleanup": {
+      "description": "スケジュールに従って履歴ログを自動的にクリーンアップし、データベース容量を解放します。",
+      "title": "ログ自動クリーンアップ"
+    },
+    "siteParams": {
+      "description": "サイトタイトル、通貨表示単位、ダッシュボード統計表示ポリシーを設定します。",
+      "title": "サイトパラメータ"
+    }
+  },
+  "siteSettings": "サイトパラメータ",
+  "siteSettingsDesc": "サイトタイトル、通貨表示単位、ダッシュボード統計表示方針を設定します。",
+  "title": "基本設定"
+}

+ 133 - 0
messages/ja/settings/data.json

@@ -0,0 +1,133 @@
+{
+  "cleanup": {
+    "backupRecommendation": "推奨:クリーンアップ前にデータベースバックアップをエクスポートして、データ復元が必要な場合に備えてください。",
+    "button": "ログをクリーンアップ",
+    "cancel": "キャンセル",
+    "cleaning": "クリーンアップ中...",
+    "confirm": "クリーンアップを確認",
+    "confirmTitle": "ログクリーンアップの確認",
+    "confirmWarning": "この操作は{range}のすべてのログレコードを完全に削除し、復元できません。",
+    "descriptionWarning": "履歴ログデータをクリーンアップしてデータベースストレージを解放します。注:統計データは保持されますが、ログ詳細は完全に削除されます。",
+    "error": "ログのクリーンアップに失敗しました",
+    "failed": "クリーンアップ失敗",
+    "logsDeleted": "✗ ログ詳細は削除されます(リクエスト/レスポンス内容、エラー情報など)",
+    "previewCount": "{count}件のログレコードを削除します",
+    "previewError": "プレビュー情報を取得できません",
+    "previewLoading": "集計中...",
+    "range": {
+      "180days": "6ヶ月前のログ(180日)",
+      "30days": "1ヶ月前のログ(30日)",
+      "7days": "1週間前のログ(7日)",
+      "90days": "3ヶ月前のログ(90日)"
+    },
+    "rangeDescription": {
+      "180days": "6ヶ月前",
+      "30days": "1ヶ月前",
+      "7days": "1週間前",
+      "90days": "3ヶ月前",
+      "default": "{days}日前"
+    },
+    "rangeLabel": "クリーンアップ範囲",
+    "statisticsRetained": "✓ 統計データは保持されます(トレンド分析用)",
+    "successMessage": "{count}件のログレコードをクリーンアップしました({batches}バッチ、所要時間{duration}秒)",
+    "willClean": "{range}のすべてのログレコードをクリーンアップします"
+  },
+  "description": "データベースのバックアップと復元を管理し、完全なインポート/エクスポートとログクリーンアップをサポートします。",
+  "export": {
+    "button": "データベースをエクスポート",
+    "descriptionFull": "完全なデータベースバックアップファイル(.dump形式)をエクスポートし、データ移行または復旧に使用できます。バックアップはPostgreSQL custom formatを使用し、自動圧縮され、異なるデータベースバージョンと互換性があります。",
+    "error": "データベースのエクスポートに失敗しました",
+    "exporting": "エクスポート中...",
+    "failed": "エクスポート失敗",
+    "successMessage": "データベースのエクスポートに成功しました!"
+  },
+  "guide": {
+    "items": {
+      "cleanup": {
+        "description": "履歴ログを物理的に削除します(取り消せません)。統計テーブルは保持されます。クリーンアップ前にデータベースバックアップをエクスポートすることをお勧めします。",
+        "title": "ログクリーンアップ"
+      },
+      "environment": {
+        "description": "Docker Composeデプロイメントが必要です。ローカル開発環境ではサポートされない可能性があります。",
+        "title": "環境要件"
+      },
+      "format": {
+        "description": "PostgreSQL custom format(.dump)を使用し、自動圧縮で異なるデータベースバージョンと互換性があります。",
+        "title": "バックアップ形式"
+      },
+      "merge": {
+        "description": "既存データを保持し、バックアップからのデータを挿入しようとします。主キーの競合がインポート失敗を引き起こす可能性があります。",
+        "title": "統合モード"
+      },
+      "overwrite": {
+        "description": "インポート前にすべての既存データを削除します。完全復元に最適です。",
+        "title": "上書きモード"
+      },
+      "safety": {
+        "description": "インポート前に現在のデータベースをバックアップとしてエクスポートすることをお勧めします。",
+        "title": "セキュリティ推奨"
+      }
+    },
+    "title": "使用説明と注意事項"
+  },
+  "import": {
+    "backupFile": "バックアップファイル:",
+    "backupRecommendation": "この操作を実行する前に、現在のデータベースをバックアップとしてエクスポートすることをお勧めします。",
+    "button": "データベースをインポート",
+    "cancel": "キャンセル",
+    "cleanFirstDescription": "インポート前にすべての既存データを削除し、データベースがバックアップと完全に一致するようにします。チェックしない場合、データのマージを試みますが、主キーの競合により失敗する可能性があります。",
+    "cleanFirstLabel": "既存データをクリア(上書きモード)",
+    "confirm": "インポートを確認",
+    "confirmMerge": "「マージモード」を選択しました。これにより、既存データを保持しながらバックアップのインポートを試みます。",
+    "confirmOverwrite": "「上書きモード」を選択しました。これにより、すべての既存データが削除された後、バックアップがインポートされます。",
+    "confirmTitle": "データベースインポートの確認",
+    "descriptionFull": "バックアップファイルからデータベースを復元します。PostgreSQL custom format(.dump)形式のバックアップファイルをサポートします。",
+    "error": "データベースのインポートに失敗しました",
+    "errorUnknown": "不明なエラー",
+    "failedMessage": "データインポート失敗、詳細ログを確認してください",
+    "fileError": ".dump形式のバックアップファイルを選択してください",
+    "fileSelected": "選択済み:{name}({size} MB)",
+    "importing": "インポート中...",
+    "noFileSelected": "最初にバックアップファイルを選択してください",
+    "parseError": "応答データの解析に失敗しました",
+    "progressTitle": "インポート進行状況",
+    "selectFileLabel": "バックアップファイルを選択",
+    "streamError": "レスポンスストリームを読み取れません",
+    "streamInterrupted": "データストリームが予期せず中断されました",
+    "streamInterruptedDesc": "インポートの進行が正常に完了しませんでした。ログを確認してデータ整合性を検証してください。問題がある場合は再度インポートしてください。",
+    "successCleanModeDesc": "すべてのデータが正常に復元されました。ページ表示が異常な場合はブラウザを更新してください。",
+    "successMergeModeDesc": "データのインポートとマージが正常に完了しました。ページ表示が異常な場合はブラウザを更新してください。",
+    "successMessage": "データインポート完了!",
+    "successWithWarnings": "データのインポートが完了しました(警告あり)",
+    "successWithWarningsDesc": "データのインポートは成功しましたが、既に存在する一部のオブジェクトはスキップされました。ページ表示が異常な場合はブラウザを更新するか、アプリを再起動してください。",
+    "warningMerge": "注意:主キーの競合が存在する場合、インポートが失敗する可能性があります。",
+    "warningOverwrite": "警告:この操作は元に戻せません。すべての現在のデータが完全に削除されます!"
+  },
+  "section": {
+    "cleanup": {
+      "description": "履歴ログデータをクリーンアップしてデータベースストレージを解放します。注:統計データは保持されますが、ログ詳細は完全に削除されます。",
+      "title": "ログクリーンアップ"
+    },
+    "export": {
+      "description": "完全なデータベースバックアップファイル(.dump形式)をエクスポートし、データ移行または復旧に使用できます。",
+      "title": "データエクスポート"
+    },
+    "import": {
+      "description": "バックアップファイルからデータベースを復元します。PostgreSQL custom format(.dump)形式のバックアップファイルをサポートします。",
+      "title": "データインポート"
+    },
+    "status": {
+      "description": "現在のデータベース接続状態と基本情報を表示します。",
+      "title": "データベースステータス"
+    }
+  },
+  "status": {
+    "connected": "データベース接続正常",
+    "error": "データベースステータスの取得に失敗しました",
+    "loading": "読み込み中...",
+    "retry": "再試行",
+    "tables": "{count} テーブル",
+    "unavailable": "データベース利用不可"
+  },
+  "title": "データ管理"
+}

+ 157 - 0
messages/ja/settings/errorRules.json

@@ -0,0 +1,157 @@
+{
+  "actions": {
+    "add": "追加",
+    "delete": "削除",
+    "edit": "編集",
+    "messages": {
+      "error": "操作が失敗しました",
+      "success": "操作が成功しました"
+    },
+    "refresh": "更新",
+    "test": "テスト"
+  },
+  "add": "エラールールを追加",
+  "addFailed": "エラールールの作成に失敗しました",
+  "addSuccess": "エラールールが正常に作成されました",
+  "cacheStats": "キャッシュ: {totalCount}件のルール",
+  "categories": {
+    "cache_limit": "キャッシュ制御制限",
+    "content_filter": "コンテンツフィルター",
+    "invalid_request": "無効なリクエスト",
+    "parameter_error": "パラメータ検証失敗",
+    "pdf_limit": "PDF ページ制限",
+    "prompt_limit": "プロンプト長制限",
+    "thinking_error": "Thinking フォーマットエラー"
+  },
+  "confirmDelete": "エラールール \"{pattern}\" を削除してもよろしいですか?",
+  "defaultRules": {
+    "cannotDelete": "デフォルトルールは削除できません",
+    "cannotDisable": "デフォルトルールは有効のままにすることをお勧めします"
+  },
+  "delete": "エラールールを削除",
+  "deleteFailed": "削除に失敗しました",
+  "deleteSuccess": "エラールールが正常に削除されました",
+  "description": "自動再試行を行わないクライアントエラールールを管理します。設定後、ルールに一致するエラーは再試行せずユーザーに直接返され、プロバイダーのサーキットブレーカーにもカウントされません。",
+  "dialog": {
+    "addDescription": "エラーメッセージの正規表現パターンを設定します。マッチしたエラーはリトライ不可能なクライアントエラーとして識別されます。",
+    "addTitle": "エラールールを追加",
+    "categoryHint": "分類管理と統計のためのエラーカテゴリを選択",
+    "categoryLabel": "ルールカテゴリ *",
+    "categoryPlaceholder": "ルールカテゴリを選択",
+    "categoryRequired": "ルールカテゴリを選択してください",
+    "creating": "作成中...",
+    "defaultRuleHint": "デフォルトルールのパターンは変更できません",
+    "descriptionLabel": "説明",
+    "descriptionPlaceholder": "オプション: 説明を追加...",
+    "editDescription": "エラールール設定を変更します。変更後、キャッシュが自動的に更新されます。",
+    "editTitle": "エラールールを編集",
+    "enableOverride": "エラーオーバーライドを有効にする",
+    "enableOverrideHint": "有効にすると、クライアントに返すエラーレスポンスとステータスコードをカスタマイズできます。元のエラーはデータベースに記録されます。現在、Claude APIエラー形式のみサポートしています。",
+    "invalidJson": "JSON形式が無効です",
+    "invalidPattern": "無効な正規表現",
+    "invalidRegex": "正規表現の構文エラー",
+    "invalidStatusCode": "ステータスコードは400-599の範囲内でなければなりません",
+    "matchFailed": "マッチなし",
+    "matchSuccess": "マッチ成功",
+    "matchedText": "マッチしたテキスト",
+    "overrideResponseHint": "空白のままにするとステータスコードのみオーバーライドします。",
+    "overrideResponseLabel": "オーバーライドレスポンス(JSON形式)",
+    "overrideResponsePlaceholder": "{\n  \"type\": \"error\",\n  \"error\": {\n    \"type\": \"invalid_request_error\",\n    \"message\": \"カスタムメッセージ\"\n  }\n}",
+    "overrideStatusCodeHint": "空白のままにするとアップストリームのステータスコードを使用します。範囲: 400-599。",
+    "overrideStatusCodeLabel": "オーバーライドステータスコード(オプション)",
+    "overrideStatusCodePlaceholder": "例: 400",
+    "patternHint": "JavaScript正規表現構文をサポート、例:prompt is too long|invalid.*request",
+    "patternLabel": "正規表現パターン *",
+    "patternPlaceholder": "正規表現を入力...",
+    "patternRequired": "正規表現パターンを入力してください",
+    "regexTester": "正規表現テスター",
+    "saving": "保存しています...",
+    "testMessageLabel": "テストメッセージ",
+    "testMessagePlaceholder": "テストするエラーメッセージを入力...",
+    "useTemplate": "Claude Error テンプレート",
+    "useTemplateConfirm": "入力済みの内容をテンプレートで上書きしますか?",
+    "validJson": "JSON 形式は有効です"
+  },
+  "disable": "エラールールが無効になりました",
+  "edit": "エラールールを編集",
+  "editFailed": "エラールールの更新に失敗しました",
+  "editSuccess": "エラールールが正常に更新されました",
+  "emptyState": "エラールールがまだありません。右上の「エラールールを追加」をクリックして設定を開始してください。",
+  "enable": "エラールールが有効になりました",
+  "form": {
+    "fields": {
+      "category": "ルールカテゴリ",
+      "description": "説明",
+      "pattern": "正規表現パターン"
+    },
+    "labels": {
+      "category": "ルールカテゴリ *",
+      "description": "説明",
+      "isEnabled": "有効状態",
+      "pattern": "正規表現パターン *"
+    },
+    "placeholders": {
+      "category": "カテゴリを選択",
+      "description": "オプション: 説明を追加...",
+      "pattern": "例: prompt is too long"
+    }
+  },
+  "nav": "エラールール",
+  "refreshCache": "ルールを同期",
+  "refreshCacheFailed": "ルールの同期に失敗しました",
+  "refreshCacheSuccess": "ルールが正常に同期され、{count} 個のエラールールがロードされました",
+  "regexTester": {
+    "matchResult": "マッチ結果",
+    "matched": "マッチしました",
+    "notMatched": "マッチしませんでした",
+    "test": "テスト",
+    "testMessage": "テストメッセージ",
+    "testMessagePlaceholder": "テストするエラーメッセージを入力...",
+    "title": "正規表現テスター"
+  },
+  "section": {
+    "title": "エラールールリスト"
+  },
+  "table": {
+    "actions": "アクション",
+    "category": "ルールカテゴリ",
+    "createdAt": "作成日時",
+    "default": "デフォルト",
+    "description": "説明",
+    "isDefault": "デフォルトルール",
+    "isEnabled": "有効状態",
+    "pattern": "正規表現パターン",
+    "status": "ステータス"
+  },
+  "tester": {
+    "category": "カテゴリ",
+    "description": "エラーメッセージを入力して、設定済みルールに一致するかと最終的な返却内容を確認します。",
+    "finalResponse": "オーバーライドレスポンス",
+    "inputLabel": "テストするエラーメッセージ",
+    "inputPlaceholder": "検証したいエラーメッセージを入力...",
+    "matchType": "マッチタイプ",
+    "matched": "エラールールに一致しました",
+    "messageRequired": "テストするエラーメッセージを入力してください",
+    "noRule": "一致したルールはありません",
+    "notMatched": "一致するルールなし",
+    "overrideStatusCode": "オーバーライドステータスコード",
+    "pattern": "パターン",
+    "ruleInfo": "一致したルール",
+    "statusCodeOnlyOverride": "ステータスコードのみオーバーライドされ、レスポンスボディはアップストリームのエラーが使用されます",
+    "testButton": "テストを実行",
+    "testFailed": "テストに失敗しました。再度お試しください",
+    "testing": "テスト中...",
+    "title": "エラールールテスト",
+    "warnings": "設定の警告"
+  },
+  "title": "エラールール管理",
+  "toggleFailed": "切り替えに失敗しました",
+  "toggleFailedError": "切り替えに失敗しました:",
+  "validation": {
+    "categoryRequired": "ルールカテゴリを選択してください",
+    "patternInvalid": "正規表現の構文エラー",
+    "patternRequired": "正規表現パターンを入力してください",
+    "patternTooComplex": "正規表現が複雑すぎます",
+    "redosRisk": "正規表現に ReDoS リスクがあります。パターンを簡略化してください"
+  }
+}

+ 17 - 0
messages/ja/settings/errors.json

@@ -0,0 +1,17 @@
+{
+  "addFailed": "プロバイダーの追加に失敗しました",
+  "addSuccess": "追加に成功しました",
+  "deleteFailed": "プロバイダーの削除に失敗しました",
+  "deleteSuccess": "削除に成功しました",
+  "editFailed": "プロバイダーの更新に失敗しました",
+  "editSuccess": "更新に成功しました",
+  "loadFailed": "通知設定の読み込みに失敗しました",
+  "saveFailed": "保存に失敗しました",
+  "saveFailed_error": "設定の保存に失敗しました",
+  "saveSuccess": "保存に成功しました",
+  "syncFailed": "同期に失敗しました",
+  "syncSuccess": "同期に成功しました",
+  "testFailed": "テストに失敗しました",
+  "testFailedRetry": "テストに失敗しました。再試行してください",
+  "unknownError": "操作中に例外が発生しました"
+}

+ 101 - 0
messages/ja/settings/index.ts

@@ -0,0 +1,101 @@
+import clientVersions from "./clientVersions.json";
+import common from "./common.json";
+import config from "./config.json";
+import data from "./data.json";
+import errorRules from "./errorRules.json";
+import errors from "./errors.json";
+import logs from "./logs.json";
+import nav from "./nav.json";
+import notifications from "./notifications.json";
+import prices from "./prices.json";
+import requestFilters from "./requestFilters.json";
+import sensitiveWords from "./sensitiveWords.json";
+import strings from "./strings.json";
+
+import providersAutoSort from "./providers/autoSort.json";
+import providersFilter from "./providers/filter.json";
+import providersGuide from "./providers/guide.json";
+import providersInlineEdit from "./providers/inlineEdit.json";
+import providersList from "./providers/list.json";
+import providersSchedulingDialog from "./providers/schedulingDialog.json";
+import providersSearch from "./providers/search.json";
+import providersSection from "./providers/section.json";
+import providersSort from "./providers/sort.json";
+import providersStrings from "./providers/strings.json";
+import providersTypes from "./providers/types.json";
+
+import providersFormApiTest from "./providers/form/apiTest.json";
+import providersFormButtons from "./providers/form/buttons.json";
+import providersFormCommon from "./providers/form/common.json";
+import providersFormDeleteDialog from "./providers/form/deleteDialog.json";
+import providersFormErrors from "./providers/form/errors.json";
+import providersFormFailureThresholdConfirmDialog from "./providers/form/failureThresholdConfirmDialog.json";
+import providersFormKey from "./providers/form/key.json";
+import providersFormMaxRetryAttempts from "./providers/form/maxRetryAttempts.json";
+import providersFormModelRedirect from "./providers/form/modelRedirect.json";
+import providersFormModelSelect from "./providers/form/modelSelect.json";
+import providersFormName from "./providers/form/name.json";
+import providersFormProviderTypes from "./providers/form/providerTypes.json";
+import providersFormProxyTest from "./providers/form/proxyTest.json";
+import providersFormSections from "./providers/form/sections.json";
+import providersFormStrings from "./providers/form/strings.json";
+import providersFormSuccess from "./providers/form/success.json";
+import providersFormTitle from "./providers/form/title.json";
+import providersFormUrl from "./providers/form/url.json";
+import providersFormUrlPreview from "./providers/form/urlPreview.json";
+import providersFormWebsiteUrl from "./providers/form/websiteUrl.json";
+
+const providersForm = {
+  ...providersFormStrings,
+  apiTest: providersFormApiTest,
+  buttons: providersFormButtons,
+  common: providersFormCommon,
+  deleteDialog: providersFormDeleteDialog,
+  errors: providersFormErrors,
+  failureThresholdConfirmDialog: providersFormFailureThresholdConfirmDialog,
+  key: providersFormKey,
+  maxRetryAttempts: providersFormMaxRetryAttempts,
+  modelRedirect: providersFormModelRedirect,
+  modelSelect: providersFormModelSelect,
+  name: providersFormName,
+  providerTypes: providersFormProviderTypes,
+  proxyTest: providersFormProxyTest,
+  sections: providersFormSections,
+  success: providersFormSuccess,
+  title: providersFormTitle,
+  url: providersFormUrl,
+  urlPreview: providersFormUrlPreview,
+  websiteUrl: providersFormWebsiteUrl,
+};
+
+const providers = {
+  ...providersStrings,
+  autoSort: providersAutoSort,
+  filter: providersFilter,
+  form: providersForm,
+  guide: providersGuide,
+  inlineEdit: providersInlineEdit,
+  list: providersList,
+  schedulingDialog: providersSchedulingDialog,
+  search: providersSearch,
+  section: providersSection,
+  sort: providersSort,
+  types: providersTypes,
+};
+
+export default {
+  nav,
+  common,
+  config,
+  providers,
+  prices,
+  sensitiveWords,
+  requestFilters,
+  logs,
+  data,
+  clientVersions,
+  notifications,
+  errors,
+  errorRules,
+  ...strings,
+};

+ 54 - 0
messages/ja/settings/logs.json

@@ -0,0 +1,54 @@
+{
+  "description": "システムログレベルを動的に調整してロギング詳細度をリアルタイムで制御します。",
+  "form": {
+    "changeNotice": "現在のレベルは {current} です、保存後 {selected} に切り替わります",
+    "currentLevel": "現在のログレベル",
+    "effectiveImmediately": "ログレベルの変更はすぐに有効になります、サービス再起動不要。",
+    "failed": "設定に失敗しました",
+    "failedError": "ログレベルの設定に失敗しました",
+    "fetchFailed": "ログレベルの取得に失敗しました",
+    "levelGuideDebug": "Debug(開発環境推奨): 詳細なデバッグ情報を含む、トラブルシューティングに適しています",
+    "levelGuideFatal": "Fatal/Error: エラーのみ表示、最小限のログ、高負荷本番環境に適しています",
+    "levelGuideInfo": "Info(本番環境推奨): 主要なビジネスイベント(プロバイダー選択、セッション再利用、価格同期)+ 警告 + エラーを表示",
+    "levelGuideTitle": "ログレベルガイド",
+    "levelGuideTrace": "Trace: 非常に詳細なトレース情報、すべての詳細を含む",
+    "levelGuideWarn": "Warn: 警告(レート制限、サーキットブレーカー開放など)+ エラーを含む",
+    "save": "設定を保存",
+    "saving": "保存しています...",
+    "selectLevel": "ログレベルを選択",
+    "success": "ログレベルを設定しました: {level}"
+  },
+  "levels": {
+    "debug": {
+      "description": "デバッグ情報 + 全レベル(開発環境推奨)",
+      "label": "Debug"
+    },
+    "error": {
+      "description": "エラーメッセージ",
+      "label": "Error"
+    },
+    "fatal": {
+      "description": "致命的エラーのみ",
+      "label": "Fatal"
+    },
+    "info": {
+      "description": "主要なビジネスイベント + 警告 + エラー(本番環境推奨)",
+      "label": "Info"
+    },
+    "trace": {
+      "description": "非常に詳細なトレース + 全レベル",
+      "label": "Trace"
+    },
+    "warn": {
+      "description": "警告 + エラー",
+      "label": "Warn"
+    }
+  },
+  "section": {
+    "description": "変更はすぐに有効になります、サービス再起動不要。",
+    "title": "ログレベルコントロール"
+  },
+  "subtitle": "ログレベルコントロール",
+  "subtitleDesc": "変更はすぐに有効になります、再起動不要。本番環境でのトラブルシューティングに便利です。",
+  "title": "ログ管理"
+}

+ 15 - 0
messages/ja/settings/nav.json

@@ -0,0 +1,15 @@
+{
+  "apiDocs": "API文書",
+  "clientVersions": "更新通知",
+  "config": "設定",
+  "data": "データ",
+  "docs": "ドキュメント",
+  "errorRules": "エラー",
+  "feedback": "報告",
+  "logs": "ログ",
+  "notifications": "通知",
+  "prices": "価格表",
+  "providers": "供給元",
+  "requestFilters": "リクエスト",
+  "sensitiveWords": "フィルター"
+}

+ 146 - 0
messages/ja/settings/notifications.json

@@ -0,0 +1,146 @@
+{
+  "bindings": {
+    "advanced": "詳細",
+    "bindTarget": "プッシュ先をバインド",
+    "boundCount": "バインド: {count}",
+    "editTemplateOverride": "上書きを編集",
+    "enable": "有効",
+    "enableType": "この通知を有効化",
+    "enabledCount": "有効: {count}",
+    "noTargets": "プッシュ先がありません",
+    "scheduleCron": "Cron",
+    "scheduleCronPlaceholder": "例: 0 9 * * *",
+    "scheduleTimezone": "タイムゾーン",
+    "templateOverride": "テンプレート上書き",
+    "templateOverrideTitle": "テンプレート上書きを編集",
+    "title": "バインド"
+  },
+  "circuitBreaker": {
+    "description": "プロバイダーが完全に遮断された時に即座にアラートを送信",
+    "enable": "サーキットブレーカーアラートを有効にする",
+    "test": "接続テスト",
+    "title": "サーキットブレーカーアラート",
+    "webhook": "Webhook URL",
+    "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=..."
+  },
+  "costAlert": {
+    "description": "ユーザー/プロバイダーの消費がクォータしきい値を超えた時にアラートをトリガー",
+    "enable": "コストアラートを有効にする",
+    "interval": "チェック間隔(分)",
+    "test": "接続テスト",
+    "threshold": "アラートしきい値",
+    "thresholdHelp": "消費がクォータの{percent}%に達した時にアラート",
+    "thresholdLabel": "アラートしきい値: {percent}%",
+    "title": "コストアラート",
+    "webhook": "Webhook URL",
+    "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...",
+    "webhookTypeFeishu": "Feishu",
+    "webhookTypeUnknown": "不明なプラットフォームです。WeComまたはFeishuのWebhook URLを使用してください",
+    "webhookTypeWeCom": "WeCom"
+  },
+  "dailyLeaderboard": {
+    "description": "毎日定時でユーザー消費トップNランキングを送信",
+    "enable": "日次ランキングを有効にする",
+    "test": "接続テスト",
+    "time": "送信時刻",
+    "timeError": "時刻形式エラー、HH:mm形式である必要があります",
+    "timePlaceholder": "09:00",
+    "title": "日次ユーザー消費ランキング",
+    "topN": "トップN件表示",
+    "webhook": "Webhook URL",
+    "webhookPlaceholder": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=..."
+  },
+  "description": "Webhook プッシュ通知を設定",
+  "form": {
+    "loadError": "通知設定の読み込みに失敗しました",
+    "loading": "読み込み中...",
+    "save": "設定を保存",
+    "saveError": "設定の保存に失敗しました",
+    "saveFailed": "保存に失敗しました",
+    "saving": "保存しています...",
+    "success": "通知設定を保存し、タスクを再スケジュールしました",
+    "testError": "接続テストに失敗しました",
+    "testFailed": "テストに失敗しました",
+    "testFailedRetry": "テストに失敗しました。再試行してください",
+    "testNoResult": "テストは成功しましたが、結果が返されませんでした",
+    "testSuccess": "テストメッセージを送信しました",
+    "webhookRequired": "まずWebhook URLを入力してください"
+  },
+  "global": {
+    "description": "すべてのプッシュ通知機能を有効または無効にする",
+    "enable": "プッシュ通知を有効にする",
+    "legacyModeDescription": "現在は旧来の単一URL通知設定を使用しています。プッシュ先を作成するとマルチターゲットモードに切り替わります。",
+    "legacyModeTitle": "互換モード",
+    "title": "通知マスタースイッチ"
+  },
+  "targetDialog": {
+    "createTitle": "プッシュ先を追加",
+    "customHeaders": "カスタムヘッダー(JSON)",
+    "customHeadersPlaceholder": "{\"X-Token\":\"...\"}",
+    "dingtalkSecret": "DingTalk シークレット",
+    "dingtalkSecretPlaceholder": "任意(署名用)",
+    "editTitle": "プッシュ先を編集",
+    "enable": "有効化",
+    "errors": {
+      "headersInvalidJson": "Headers は有効な JSON である必要があります",
+      "headersMustBeObject": "Headers は JSON オブジェクトである必要があります",
+      "headersValueMustBeString": "Headers の値は文字列である必要があります"
+    },
+    "name": "名前",
+    "namePlaceholder": "例: Ops グループ",
+    "proxy": {
+      "fallbackToDirect": "プロキシ失敗時に直結へフォールバック",
+      "title": "プロキシ",
+      "toggle": "プロキシ設定を切り替え",
+      "url": "プロキシURL",
+      "urlPlaceholder": "http://127.0.0.1:7890"
+    },
+    "selectType": "プラットフォームを選択",
+    "telegramBotToken": "Telegram Bot Token",
+    "telegramBotTokenPlaceholder": "例: 123456:ABCDEF...",
+    "telegramChatId": "Telegram Chat ID",
+    "telegramChatIdPlaceholder": "例: -1001234567890",
+    "type": "プラットフォーム",
+    "types": {
+      "custom": "カスタムWebhook",
+      "dingtalk": "DingTalk",
+      "feishu": "Feishu",
+      "telegram": "Telegram",
+      "wechat": "WeCom"
+    },
+    "webhookUrl": "Webhook URL",
+    "webhookUrlPlaceholder": "https://example.com/webhook"
+  },
+  "targets": {
+    "add": "追加",
+    "bindingsSaved": "バインドを保存しました",
+    "created": "プッシュ先を作成しました",
+    "delete": "削除",
+    "deleteConfirm": "このプッシュ先を削除しますか?関連するバインドも削除されます。",
+    "deleteConfirmTitle": "プッシュ先を削除",
+    "deleted": "プッシュ先を削除しました",
+    "description": "プッシュ先を管理します。WeCom、Feishu、DingTalk、Telegram、カスタムWebhookに対応。",
+    "edit": "編集",
+    "emptyHint": "プッシュ先がありません。「追加」で作成してください。",
+    "enable": "有効化",
+    "lastTestAt": "最終テスト",
+    "lastTestFailed": "テスト失敗",
+    "lastTestNever": "未テスト",
+    "lastTestSuccess": "テスト成功",
+    "statusDisabled": "無効",
+    "statusEnabled": "有効",
+    "test": "テスト",
+    "testSelectType": "テスト種類を選択",
+    "title": "プッシュ先",
+    "update": "保存",
+    "updated": "プッシュ先を更新しました"
+  },
+  "templateEditor": {
+    "insert": "挿入",
+    "jsonInvalid": "JSON が不正です",
+    "placeholder": "JSON テンプレートを入力...",
+    "placeholders": "プレースホルダー",
+    "title": "テンプレート(JSON)"
+  },
+  "title": "プッシュ通知"
+}

+ 191 - 0
messages/ja/settings/prices.json

@@ -0,0 +1,191 @@
+{
+  "title": "価格表",
+  "description": "プラットフォーム基本設定とモデル価格を管理します",
+  "section": {
+    "title": "モデル価格",
+    "description": "AIモデルの価格設定を管理します"
+  },
+  "searchPlaceholder": "モデル名を検索...",
+  "filters": {
+    "all": "すべて",
+    "local": "ローカル",
+    "anthropic": "Anthropic",
+    "openai": "OpenAI",
+    "vertex": "Vertex"
+  },
+  "badges": {
+    "local": "ローカル"
+  },
+  "capabilities": {
+    "assistantPrefill": "アシスタント事前入力",
+    "computerUse": "コンピューター利用",
+    "functionCalling": "関数呼び出し",
+    "pdfInput": "PDF入力",
+    "promptCaching": "プロンプトキャッシュ",
+    "reasoning": "推論",
+    "responseSchema": "レスポンススキーマ",
+    "toolChoice": "ツール選択",
+    "vision": "ビジョン",
+    "statusSupported": "対応",
+    "statusUnsupported": "未対応",
+    "tooltip": "{label}: {status}"
+  },
+  "sync": {
+    "button": "クラウド価格表を同期",
+    "syncing": "同期中...",
+    "checking": "競合を確認中...",
+    "successWithChanges": "価格表を更新: {added}件追加、{updated}件更新、{unchanged}件変化なし",
+    "successNoChanges": "価格表は最新です。更新の必要はありません",
+    "failed": "同期に失敗しました",
+    "failedError": "同期に失敗しました: {error}",
+    "failedNoResult": "価格表は更新されましたが結果が返されていません",
+    "noModels": "モデル価格が見つかりません",
+    "partialFailure": "一部更新が成功しましたが、{failed}件のモデルが失敗しました",
+    "failedModels": "失敗モデル: {models}",
+    "skippedConflicts": "{count}件の手動モデルをスキップしました"
+  },
+  "conflict": {
+    "title": "上書きする項目を選択",
+    "description": "以下のモデルには手動で設定された価格があります。チェックした項目はLiteLLM価格で上書きされ、チェックしない項目は現在のままです",
+    "searchPlaceholder": "モデルを検索...",
+    "table": {
+      "modelName": "モデル",
+      "manualPrice": "手動価格",
+      "litellmPrice": "LiteLLM価格",
+      "action": "操作内容"
+    },
+    "viewDiff": "差異を表示",
+    "diffTitle": "価格差異",
+    "diff": {
+      "field": "フィールド",
+      "manual": "手動",
+      "litellm": "LiteLLM",
+      "inputPrice": "入力価格",
+      "outputPrice": "出力価格",
+      "imagePrice": "画像価格",
+      "provider": "プロバイダー",
+      "mode": "タイプ"
+    },
+    "pagination": {
+      "showing": "{from}〜{to}件を表示 (全{total}件)"
+    },
+    "selectedCount": "{count}/{total}件のモデルを選択",
+    "noMatch": "一致するモデルが見つかりません",
+    "noConflicts": "競合なし",
+    "applyOverwrite": "上書きを適用",
+    "applying": "適用中..."
+  },
+  "table": {
+    "modelName": "モデル名",
+    "provider": "プロバイダー",
+    "capabilities": "機能",
+    "price": "価格",
+    "inputPrice": "入力価格 ($/M)",
+    "outputPrice": "出力価格 ($/M)",
+    "priceInput": "入力",
+    "priceOutput": "出力",
+    "pricePerRequest": "回",
+    "cacheReadPrice": "キャッシュ読み取り ($/M)",
+    "cacheCreationPrice": "キャッシュ作成 ($/M)",
+    "cache5m": "5m",
+    "cache1h": "1h+",
+    "copyModelId": "モデルIDをコピー",
+    "updatedAt": "更新日時",
+    "actions": "操作内容",
+    "typeChat": "チャット",
+    "typeImage": "画像生成",
+    "typeCompletion": "補完",
+    "typeUnknown": "不明",
+    "loading": "読み込み中...",
+    "noMatch": "一致するモデルが見つかりません",
+    "noDataTitle": "価格データがありません",
+    "noDataHint": "システムは組み込み価格表を持っています。上のボタンを使用して同期または更新してください。"
+  },
+  "pagination": {
+    "showing": "{from}〜{to}件を表示 (全{total}件)",
+    "previous": "前へ",
+    "next": "次へ",
+    "perPageLabel": "1ページあたり",
+    "perPage": "1ページあたり{size}件"
+  },
+  "stats": {
+    "totalModels": "合計{count}個のモデル",
+    "searchResults": "{count}件の検索結果",
+    "lastUpdated": "最終更新: {time}"
+  },
+  "dialog": {
+    "title": "モデル価格表を更新",
+    "description": "モデル価格データを含むJSONまたはTOMLファイルを選択してアップロード",
+    "selectFile": "JSON/TOMLファイルをクリックして選択、またはドラッグしてください",
+    "fileSizeLimit": "ファイルサイズは10MBを超えることはできません",
+    "fileSizeLimitSmall": "ファイルサイズは10MB以下です",
+    "invalidFileType": "JSONまたはTOML形式のファイルを選択してください",
+    "fileTooLarge": "ファイルサイズが10MBを超えています",
+    "upload": "アップロードして更新",
+    "uploading": "アップロード中...",
+    "updatePriceTable": "価格表を更新",
+    "updating": "更新しています...",
+    "selectJson": "ファイルを選択",
+    "updateSuccess": "価格表が正常に更新されました。{count}個のモデルを更新しました",
+    "updateFailed": "更新に失敗しました",
+    "systemHasBuiltIn": "システムは組み込み価格表を持っています",
+    "manualDownload": "手動でダウンロードすることもできます",
+    "latestPriceTable": "クラウド価格表",
+    "andUploadViaButton": "、上のボタンでアップロードしてください",
+    "cloudModelCountLoading": "クラウドモデル数を読み込み中...",
+    "cloudModelCountFailed": "クラウドモデル数の読み込みに失敗しました",
+    "supportedModels": "現在{count}個のモデルをサポート",
+    "results": {
+      "title": "更新結果",
+      "total": "合計: {total}個のモデル",
+      "success": "成功: {success}件",
+      "failed": "失敗: {failed}",
+      "skipped": "スキップ: {skipped}",
+      "more": " (+{count})",
+      "details": "詳細",
+      "viewDetails": "詳細ログを表示"
+    }
+  },
+  "addModel": "モデルを追加",
+  "editModel": "モデルを編集",
+  "deleteModel": "モデルを削除",
+  "addModelDescription": "新しいモデル価格設定を手動で追加します",
+  "editModelDescription": "モデルの価格設定を編集します",
+  "deleteConfirm": "モデル {name} を削除してもよろしいですか?この操作は元に戻せません。",
+  "form": {
+    "modelName": "モデルID",
+    "modelNamePlaceholder": "例: gpt-5.2-codex",
+    "modelNameRequired": "モデルIDは必須です",
+    "displayName": "表示名 (任意)",
+    "displayNamePlaceholder": "例: GPT-5.2 Codex",
+    "type": "タイプ",
+    "provider": "プロバイダー",
+    "providerPlaceholder": "例: openai",
+    "requestPrice": "呼び出し単価 ($/request)",
+    "inputPrice": "入力価格 ($/M tokens)",
+    "outputPrice": "出力価格 ($/M tokens)",
+    "outputPriceImage": "出力価格 ($/image)",
+    "cacheReadPrice": "キャッシュ読み取り価格 ($/M tokens)",
+    "cacheCreationPrice5m": "キャッシュ作成価格 (5m,$/M tokens)",
+    "cacheCreationPrice1h": "キャッシュ作成価格 (1h+,$/M tokens)"
+  },
+  "drawer": {
+    "prefillLabel": "既存モデルを検索してプリフィル",
+    "prefillEmpty": "一致するモデルが見つかりません",
+    "prefillFailed": "検索に失敗しました",
+    "promptCachingHint": "モデルがキャッシュに対応している場合のみ有効化し、下のキャッシュ価格を設定してください",
+    "cachePricingTitle": "キャッシュ価格"
+  },
+  "actions": {
+    "edit": "編集",
+    "more": "その他の操作",
+    "delete": "削除"
+  },
+  "toast": {
+    "createSuccess": "モデルを追加しました",
+    "updateSuccess": "モデルを更新しました",
+    "deleteSuccess": "モデルを削除しました",
+    "saveFailed": "保存に失敗しました",
+    "deleteFailed": "削除に失敗しました"
+  }
+}

+ 16 - 0
messages/ja/settings/providers/autoSort.json

@@ -0,0 +1,16 @@
+{
+  "button": "優先度を自動ソート",
+  "changeCount": "{count} 件のプロバイダーが更新されます",
+  "changesTitle": "変更詳細",
+  "confirm": "変更を適用",
+  "costMultiplierHeader": "コスト倍率",
+  "dialogDescription": "コスト倍率に基づいて優先度を自動割り当て(低コスト = 高優先度)",
+  "dialogTitle": "プロバイダー優先度の自動ソート",
+  "error": "優先度の更新に失敗しました",
+  "noChanges": "変更不要(ソート済み)",
+  "priorityChangeHeader": "優先度変更",
+  "priorityHeader": "優先度",
+  "providerHeader": "プロバイダー",
+  "providersHeader": "プロバイダー",
+  "success": "{count} 件のプロバイダーの優先度を更新しました"
+}

+ 13 - 0
messages/ja/settings/providers/filter.json

@@ -0,0 +1,13 @@
+{
+  "circuitBroken": "サーキットブレーカー",
+  "groups": {
+    "all": "すべて",
+    "default": "default",
+    "label": "グループ:"
+  },
+  "status": {
+    "active": "有効",
+    "all": "すべてのステータス",
+    "inactive": "無効"
+  }
+}

+ 157 - 0
messages/ja/settings/providers/form/apiTest.json

@@ -0,0 +1,157 @@
+{
+  "apiFormat": "プロバイダータイプ",
+  "apiFormatDesc": "手動で変更しない限り、ルーティング設定のプロバイダータイプと同期",
+  "chunksCount": "{count} チャンク受信 ({format})",
+  "chunksReceived": "受信したチャンク",
+  "close": "閉じる",
+  "copyFailed": "コピー失敗",
+  "copyFormat": {
+    "errorDetails": "エラー詳細",
+    "message": "メッセージ",
+    "testResult": "テスト結果"
+  },
+  "copyResult": "結果をコピー",
+  "copySuccess": "クリップボードにコピーしました",
+  "customConfig": "カスタム",
+  "customPayloadDesc": "カスタムJSONペイロードを入力してデフォルトのリクエストボディを上書き",
+  "customPayloadPlaceholder": "{\"model\": \"...\", \"messages\": [...]}",
+  "disclaimer": {
+    "confirmConfig": "プロバイダーURL、APIキー、モデル設定を確認してください",
+    "realRequest": "テストはプロバイダーに実際のリクエストを送信し、少量のクォータを消費する可能性があります",
+    "resultReference": "プロバイダーによって結果が異なる場合があり、参考用です",
+    "title": "注意事項"
+  },
+  "error": "エラーメッセージ",
+  "failed": "失敗",
+  "fillKeyFirst": "まずAPIキーを入力してください",
+  "fillUrlFirst": "まずプロバイダーURLを入力してください",
+  "formatAnthropicMessages": "Claude (Anthropic Messages API)",
+  "formatOpenAIChat": "OpenAI Compatible",
+  "formatOpenAIResponses": "Codex (Response API)",
+  "geminiAuthFallback": {
+    "desc": "実際のプロキシ転送はヘッダー認証のみを使用するため、リクエストが失敗する可能性があります",
+    "warning": "ヘッダー認証に失敗し、URLパラメータ認証を使用しました"
+  },
+  "invalidUrl": "プロバイダーURLが無効です(http/httpsのみ対応)",
+  "model": "モデル",
+  "noResult": "テスト成功ですが結果が返されませんでした",
+  "presetConfig": "プリセット",
+  "presetDesc": "プリセットテンプレートには、リレーサービス検証用の本物のCLIリクエストパターンが含まれています",
+  "requestConfig": "リクエスト設定",
+  "response": "応答内容",
+  "responseModel": "応答モデル",
+  "responseTime": "応答時間",
+  "resultCard": {
+    "copyText": {
+      "contentCheck": "コンテンツ検証",
+      "error": "エラー",
+      "httpCheck": "HTTPチェック",
+      "httpStatus": "HTTPステータス",
+      "inputOutput": "入力 {input} / 出力 {output} トークン",
+      "latency": "レイテンシ",
+      "latencyCheck": "レイテンシチェック",
+      "message": "メッセージ",
+      "model": "モデル",
+      "response": "応答",
+      "status": "ステータス",
+      "testedAt": "テスト日時",
+      "usage": "使用量",
+      "validationDetails": "検証詳細"
+    },
+    "dialogTitle": "プロバイダーテスト詳細",
+    "errorDetails": {
+      "title": "エラー詳細",
+      "type": "エラータイプ"
+    },
+    "judgment": "判定結果",
+    "labels": {
+      "content": "コンテンツ",
+      "error": "エラー",
+      "firstByte": "最初のバイト",
+      "http": "HTTP",
+      "latency": "レイテンシ",
+      "model": "モデル",
+      "responsePreview": "応答プレビュー",
+      "totalLatency": "合計レイテンシ"
+    },
+    "rawResponse": {
+      "hint": "ここに生のレスポンス内容が表示されます。キーワードがレスポンスに含まれているか確認できます。",
+      "title": "生のレスポンスボディ"
+    },
+    "status": {
+      "green": "利用可能",
+      "red": "利用不可",
+      "yellow": "不安定"
+    },
+    "streamInfo": {
+      "chunksCount": "チャンク数",
+      "isStreaming": "ストリーミング",
+      "no": "いいえ",
+      "title": "ストリーム応答情報",
+      "yes": "はい"
+    },
+    "timing": {
+      "firstByte": "最初のバイト",
+      "testedAt": "テスト日時",
+      "title": "タイミング情報",
+      "totalLatency": "合計レイテンシ"
+    },
+    "tokenUsage": {
+      "cacheCreation": "キャッシュ作成",
+      "cacheRead": "キャッシュ読取",
+      "input": "入力",
+      "output": "出力",
+      "title": "トークン使用量"
+    },
+    "validation": {
+      "content": {
+        "failed": "ターゲットが見つかりません",
+        "passed": "ターゲット文字列を含む",
+        "target": "ターゲット",
+        "title": "Tier 3: コンテンツ検証"
+      },
+      "failed": "失敗",
+      "http": {
+        "failed": "4xx/5xx 失敗",
+        "passed": "2xx/3xx OK",
+        "statusCode": "ステータスコード",
+        "title": "Tier 1: HTTPステータス"
+      },
+      "latency": {
+        "actual": "実際のレイテンシ",
+        "failed": "閾値超過",
+        "passed": "閾値内",
+        "title": "Tier 2: レイテンシ閾値"
+      },
+      "passed": "合格",
+      "timeout": "タイムアウト",
+      "title": "三層検証詳細"
+    }
+  },
+  "selectApiFormat": "テストするプロバイダータイプを選択",
+  "selectPreset": "プリセットテンプレートを選択",
+  "streamFormat": "ストリーム形式",
+  "streamInfo": "ストリーム応答情報",
+  "streamResponse": "ストリーム応答",
+  "success": "成功しました",
+  "successContains": "成功検出キーワード",
+  "successContainsDesc": "成功と見なすには、レスポンスにこのキーワードが含まれている必要があります",
+  "successContainsPlaceholder": "pong",
+  "testApi": "プロバイダーモデルテスト",
+  "testFailed": "テスト失敗",
+  "testFailedRetry": "テスト失敗、再試行してください",
+  "testModel": "テストモデル",
+  "testModelDesc": "空欄の場合はデフォルトモデルを使用、手動入力も可能",
+  "testSuccess": "モデルテスト成功",
+  "testing": "テスト中...",
+  "timeout": {
+    "desc": "テストリクエストの最大待機時間(5〜120秒)",
+    "geminiHint": "、Gemini Thinkingモデルは60秒以上を推奨",
+    "label": "タイムアウト(秒)"
+  },
+  "truncatedBrief": "先頭 {length} 文字を表示、全文は「詳細を見る」をクリック",
+  "truncatedPreview": "先頭 {length} 文字を表示、全文はコピーして確認",
+  "unknown": "不明",
+  "usage": "トークン使用量",
+  "viewDetails": "詳細を見る"
+}

+ 9 - 0
messages/ja/settings/providers/form/buttons.json

@@ -0,0 +1,9 @@
+{
+  "collapseAll": "高度な設定をすべて折りたたむ",
+  "delete": "削除",
+  "expandAll": "高度な設定をすべて展開",
+  "submit": "追加を確定",
+  "submitting": "追加中...",
+  "update": "更新を確定",
+  "updating": "更新しています..."
+}

+ 3 - 0
messages/ja/settings/providers/form/common.json

@@ -0,0 +1,3 @@
+{
+  "core": "コア"
+}

+ 6 - 0
messages/ja/settings/providers/form/deleteDialog.json

@@ -0,0 +1,6 @@
+{
+  "cancel": "キャンセル",
+  "confirm": "削除を確定",
+  "description": "プロバイダー「{name}」を削除しますか?この操作は元に戻せません。",
+  "title": "プロバイダーを削除"
+}

+ 8 - 0
messages/ja/settings/providers/form/errors.json

@@ -0,0 +1,8 @@
+{
+  "addFailed": "プロバイダーの追加に失敗しました",
+  "deleteFailed": "プロバイダーの削除に失敗しました",
+  "groupTagTooLong": "プロバイダーグループが長すぎます(合計{max}文字まで)",
+  "invalidUrl": "有効な API アドレスを入力してください",
+  "invalidWebsiteUrl": "有効な公式サイト URL を入力してください",
+  "updateFailed": "プロバイダーの更新に失敗しました"
+}

+ 13 - 0
messages/ja/settings/providers/form/failureThresholdConfirmDialog.json

@@ -0,0 +1,13 @@
+{
+  "cancel": "キャンセル",
+  "confirm": "保存を確定",
+  "confirmQuestion": "この設定を保存してもよろしいですか?",
+  "descriptionDisabledAction": "サーキットブレーカーを無効化",
+  "descriptionDisabledMiddle": "に設定しています。これは",
+  "descriptionDisabledPrefix": "サーキットブレーカーの失敗閾値を",
+  "descriptionDisabledSuffix": "することを意味し、プロバイダーは連続した失敗によって遮断されません。",
+  "descriptionDisabledValue": "0",
+  "descriptionHighValuePrefix": "サーキットブレーカーの失敗閾値を",
+  "descriptionHighValueSuffix": "に設定しています。これは高い値であり、プロバイダーが多数の失敗の後にのみ遮断される可能性があります。",
+  "title": "特別な設定を確認"
+}

+ 7 - 0
messages/ja/settings/providers/form/key.json

@@ -0,0 +1,7 @@
+{
+  "currentKey": "現在のキー: {key}",
+  "label": "API キー",
+  "leaveEmpty": "(空欄のままにすると変更しません)",
+  "leaveEmptyDesc": "空欄のままにすると既存のキーを保持します",
+  "placeholder": "API キーを入力"
+}

+ 5 - 0
messages/ja/settings/providers/form/maxRetryAttempts.json

@@ -0,0 +1,5 @@
+{
+  "desc": "初回呼び出しを含め、同一プロバイダーで最大何回まで試行してから切り替えるか。空欄の場合はシステム既定値を使用します。",
+  "label": "単一プロバイダーの最大試行回数",
+  "placeholder": "2"
+}

+ 14 - 0
messages/ja/settings/providers/form/modelRedirect.json

@@ -0,0 +1,14 @@
+{
+  "add": "追加",
+  "addNewRule": "新規ルールを追加",
+  "alreadyExists": "モデル \"{model}\" のリダイレクトルールは既に存在します",
+  "currentRules": "現在のルール ({count})",
+  "description": "Claude Code クライアントがリクエストするモデル(例:claude-sonnet-4.5)を、上流プロバイダーが実際にサポートするモデル(例:glm-4.6、gemini-pro)にリダイレクトします。コスト最適化やサードパーティAIサービスへの接続に使用します。",
+  "emptyState": "リダイレクトルールがありません。ルールを追加すると、システムは自動的にリクエスト内のモデル名を書き換えます。",
+  "sourceEmpty": "ソースモデル名を入力してください",
+  "sourceModel": "ユーザーがリクエストするモデル",
+  "sourcePlaceholder": "例:claude-sonnet-4-5-20250929",
+  "targetEmpty": "ターゲットモデル名を入力してください",
+  "targetModel": "実際に転送されるモデル",
+  "targetPlaceholder": "例:glm-4.6"
+}

+ 20 - 0
messages/ja/settings/providers/form/modelSelect.json

@@ -0,0 +1,20 @@
+{
+  "allowAllModels": "すべての {type} モデルを許可",
+  "claude": "Claude",
+  "clear": "クリア",
+  "gemini": "Gemini",
+  "loading": "読み込み中...",
+  "manualAdd": "手動でモデルを追加",
+  "manualDesc": "任意のモデル名を追加できます(価格表のモデルに限定されません)",
+  "manualPlaceholder": "モデル名を入力(例:gpt-5-turbo)",
+  "notFound": "モデルが見つかりません",
+  "openai": "OpenAI",
+  "refresh": "モデルリストを更新",
+  "searchPlaceholder": "モデル名を検索...",
+  "selectAll": "すべて選択 ({count})",
+  "selectedCount": "{count} 個のモデルを選択済み",
+  "sourceFallback": "ローカル",
+  "sourceFallbackDesc": "ローカル価格表のモデルリストを使用(上流が利用不可または未対応)",
+  "sourceUpstream": "上流",
+  "sourceUpstreamDesc": "モデルリストは上流プロバイダーAPIから取得"
+}

+ 4 - 0
messages/ja/settings/providers/form/name.json

@@ -0,0 +1,4 @@
+{
+  "label": "プロバイダー名 *",
+  "placeholder": "例: Zhipu"
+}

+ 10 - 0
messages/ja/settings/providers/form/providerTypes.json

@@ -0,0 +1,10 @@
+{
+  "claude": "Claude (Anthropic Messages API)",
+  "claudeAuth": "Claude (Anthropic Auth Token)",
+  "codex": "Codex (Response API)",
+  "gemini": "Gemini (Google Gemini API)",
+  "geminiCli": "Gemini CLI",
+  "geminiCliDisabled": "",
+  "openaiCompatible": "OpenAI Compatible",
+  "openaiCompatibleDisabled": " - 開発中"
+}

+ 21 - 0
messages/ja/settings/providers/form/proxyTest.json

@@ -0,0 +1,21 @@
+{
+  "connectionFailed": "接続失敗",
+  "connectionMethod": "接続方式:",
+  "connectionSuccess": "接続成功",
+  "direct": "直接接続",
+  "errorType": "エラータイプ:",
+  "fillUrlFirst": "まずプロバイダーURLを入力してください",
+  "networkError": "ネットワークエラー:",
+  "noResult": "テスト成功ですが結果が返されませんでした",
+  "proxy": "プロキシ",
+  "proxyError": "プロキシエラー:",
+  "responseTime": "応答時間:",
+  "statusCode": "ステータスコード:",
+  "testConnection": "接続テスト",
+  "testFailed": "テスト失敗",
+  "testFailedRetry": "テストに失敗しました。再試行してください",
+  "testing": "テスト中...",
+  "timeoutError": "接続タイムアウト(5秒)。以下を確認してください:\n1. プロキシサーバーにアクセスできるか\n2. プロキシアドレスとポートが正しいか\n3. プロキシ認証情報が正しいか",
+  "viaDirect": "(直接接続)",
+  "viaProxy": "(プロキシ経由)"
+}

+ 313 - 0
messages/ja/settings/providers/form/sections.json

@@ -0,0 +1,313 @@
+{
+  "apiTest": {
+    "desc": "プロバイダーのモデルが利用可能かをテストします。既定ではルーティング設定で選択したプロバイダー種別に従います。",
+    "summary": "プロバイダーとモデルの接続性を確認",
+    "testLabel": "プロバイダーモデルをテスト",
+    "title": "プロバイダーモデルテスト"
+  },
+  "circuitBreaker": {
+    "desc": "連続失敗時に自動的にブレークして全体の品質を保護します",
+    "failureThreshold": {
+      "desc": "何回連続失敗でブレークするか",
+      "label": "失敗しきい値(回)",
+      "placeholder": "5"
+    },
+    "maxRetryAttempts": {
+      "desc": "初回呼び出しを含め、同一プロバイダーで試行する上限。超えると他のプロバイダーへ切り替えます。未入力の場合はデフォルト値を使用。",
+      "label": "プロバイダーごとの最大試行回数",
+      "placeholder": "2"
+    },
+    "openDuration": {
+      "desc": "ブレーク後、半開に移行するまでの時間",
+      "label": "ブレーク時間(分)",
+      "placeholder": "30"
+    },
+    "successThreshold": {
+      "desc": "半開状態で何回成功したら完全回復するか",
+      "label": "回復しきい値(回)",
+      "placeholder": "2"
+    },
+    "summary": "{failureThreshold} 回失敗 / {openDuration} 分間ブレーク / {successThreshold} 回成功で回復 / 各プロバイダー最大 {maxRetryAttempts} 回試行",
+    "title": "サーキットブレーカー設定"
+  },
+  "codexStrategy": {
+    "desc": "Codex リクエストの instructions フィールドの扱いを制御します。上流ゲートウェイとの互換性に影響します。",
+    "hint": "ヒント: 88code や foxcode など一部の厳格な Codex 中継では公式 instructions が必要です。「自動」または「公式を強制」を選択してください。",
+    "select": {
+      "auto": {
+        "desc": "クライアントの instructions を透過し、400 エラー時は公式プロンプトで自動再試行",
+        "label": "自動(推奨)"
+      },
+      "force": {
+        "desc": "常に公式の Codex CLI instructions を使用(約 4000+ 文字)",
+        "label": "公式を強制"
+      },
+      "keep": {
+        "desc": "常にクライアントの instructions を透過し、自動再試行しない(緩い中継向け)",
+        "label": "そのまま透過"
+      },
+      "label": "ポリシー選択",
+      "placeholder": "戦略を選択"
+    },
+    "summary": {
+      "auto": "自動(推奨)",
+      "force": "公式を強制",
+      "keep": "そのまま透過"
+    },
+    "title": "Codex Instructions ポリシー"
+  },
+  "mcpPassthrough": {
+    "desc": "有効にすると、MCP ツール呼び出しを指定された AI プロバイダにパススルーします(例:minimax の画像認識、Web 検索)",
+    "hint": "ヒント: MCP パススルーにより、Claude Code クライアントは第三者の AI プロバイダー提供のツール機能(画像認識、Web 検索など)を使用できます",
+    "select": {
+      "custom": {
+        "desc": "カスタム MCP サービスにパススルー(予約、未実装)",
+        "label": "カスタム"
+      },
+      "glm": {
+        "desc": "GLM MCP サービスにパススルー(画像分析、動画分析などをサポート)",
+        "label": "GLM"
+      },
+      "label": "パススルータイプ",
+      "minimax": {
+        "desc": "minimax MCP サービスにパススルー(画像認識、Web 検索などをサポート)",
+        "label": "Minimax"
+      },
+      "none": {
+        "desc": "MCP パススルーを有効にしません(デフォルト)",
+        "label": "無効"
+      },
+      "placeholder": "パススルータイプを選択"
+    },
+    "summary": {
+      "custom": "カスタム (予約)",
+      "glm": "GLM",
+      "minimax": "Minimax",
+      "none": "無効"
+    },
+    "title": "MCP パススルー設定",
+    "urlAuto": "自動抽出: {url}",
+    "urlDesc": "MCP サービスベース URL。空のままにすると、プロバイダー URL から自動的に抽出されます",
+    "urlLabel": "MCP パススルー URL",
+    "urlPlaceholder": "https://api.minimaxi.com"
+  },
+  "proxy": {
+    "desc": "プロキシを設定して接続性を改善します(HTTP、HTTPS、SOCKS4、SOCKS5)",
+    "fallback": {
+      "desc": "有効にすると、プロキシ接続が失敗した場合に直接接続を試行します",
+      "label": "プロキシ失敗時は直接接続にフォールバック"
+    },
+    "summary": {
+      "configured": "プロキシ設定済み",
+      "fallback": "(フォールバック有効)",
+      "none": "未設定"
+    },
+    "test": {
+      "desc": "設定したプロキシ経由でプロバイダー URL への接続をテストします(HEAD リクエスト、課金なし)",
+      "label": "接続テスト"
+    },
+    "title": "プロキシ設定",
+    "url": {
+      "formats": "対応フォーマット:",
+      "label": "プロキシ URL",
+      "optional": "(任意)",
+      "placeholder": "例: http://proxy.example.com:8080 または socks5://127.0.0.1:1080"
+    }
+  },
+  "rateLimit": {
+    "dailyResetMode": {
+      "desc": {
+        "fixed": "毎日決まった時刻にクォータをリセット",
+        "rolling": "初回呼び出しから24時間後にリセット"
+      },
+      "label": "日次リセットモード",
+      "options": {
+        "fixed": "固定時刻リセット",
+        "rolling": "ローリング(24時間)"
+      }
+    },
+    "dailyResetTime": {
+      "label": "日次リセット時刻 (HH:mm)"
+    },
+    "limit5h": {
+      "label": "5時間の上限 (USD)",
+      "placeholder": "空欄で無制限"
+    },
+    "limitConcurrent": {
+      "label": "同時セッション上限",
+      "placeholder": "0 は無制限"
+    },
+    "limitDaily": {
+      "label": "1日の支出上限 (USD)",
+      "placeholder": "空欄は無制限"
+    },
+    "limitMonthly": {
+      "label": "月の上限 (USD)",
+      "placeholder": "空欄で無制限"
+    },
+    "limitTotal": {
+      "label": "総消費上限 (USD)",
+      "placeholder": "空欄で無制限"
+    },
+    "limitWeekly": {
+      "label": "週の上限 (USD)",
+      "placeholder": "空欄で無制限"
+    },
+    "summary": {
+      "concurrent": "同時: {count}",
+      "daily": "日: {amount}({resetTime}にリセット)",
+      "fiveHour": "5h: ${amount}",
+      "monthly": "月: ${amount}",
+      "none": "無制限",
+      "total": "総: ${amount}",
+      "weekly": "週: ${amount}"
+    },
+    "title": "レート制限"
+  },
+  "routing": {
+    "cacheTtl": {
+      "desc": "プロンプトキャッシュのTTLを強制設定。cache_controlを含むリクエストにのみ適用されます。",
+      "label": "キャッシュTTLオーバーライド",
+      "options": {
+        "1h": "1時間",
+        "5m": "5分",
+        "inherit": "オーバーライドしない(クライアントに従う)"
+      }
+    },
+    "codexOverrides": {
+      "parallelToolCalls": {
+        "help": "並列の tool calls を許可するかどうかを制御します。「クライアントに従う」は parallel_tool_calls を変更しません。無効化すると並列度が下がる可能性があります。",
+        "label": "並列ツール呼び出しオーバーライド",
+        "options": {
+          "false": "強制無効",
+          "inherit": "オーバーライドしない(クライアントに従う)",
+          "true": "強制有効"
+        }
+      },
+      "reasoningEffort": {
+        "help": "回答前にモデルが使う推論の強度(推論トークン量)を制御します。「クライアントに従う」はリクエストを変更しません。その他の値は reasoning.effort を強制します。注意: none は GPT-5.1 のみ、xhigh は GPT-5.1-Codex-Max のみ対応で、未対応モデルではエラーになります。",
+        "label": "推論強度オーバーライド",
+        "options": {
+          "high": "high",
+          "inherit": "オーバーライドしない(クライアントに従う)",
+          "low": "low",
+          "medium": "medium(デフォルト)",
+          "minimal": "minimal",
+          "none": "none(GPT-5.1 のみ)",
+          "xhigh": "xhigh(GPT-5.1-Codex-Max のみ)"
+        }
+      },
+      "reasoningSummary": {
+        "help": "推論サマリーを返すかどうかを制御します。auto は簡潔、detailed は詳細です。「クライアントに従う」は reasoning.summary を変更しません。",
+        "label": "推論サマリーオーバーライド",
+        "options": {
+          "auto": "auto",
+          "detailed": "detailed",
+          "inherit": "オーバーライドしない(クライアントに従う)"
+        }
+      },
+      "textVerbosity": {
+        "help": "モデル出力の冗長さを制御します。low は簡潔、high は詳細です。「クライアントに従う」は text.verbosity を変更しません。",
+        "label": "出力の詳細度オーバーライド",
+        "options": {
+          "high": "high",
+          "inherit": "オーバーライドしない(クライアントに従う)",
+          "low": "low",
+          "medium": "medium(デフォルト)"
+        }
+      }
+    },
+    "context1m": {
+      "desc": "1M コンテキストウィンドウのサポートを設定します。Sonnet モデル(claude-sonnet-4-5、claude-sonnet-4)にのみ適用されます。有効時は段階的料金が適用されます。",
+      "label": "1M コンテキストウィンドウ",
+      "options": {
+        "disabled": "無効",
+        "forceEnable": "強制有効化",
+        "inherit": "継承(クライアントに従う)"
+      }
+    },
+    "joinClaudePool": {
+      "desc": "有効にすると、Claude 系のプロバイダーと共に負荷分散に参加します",
+      "help": "claude-* へのリダイレクトがある場合のみ利用できます。ユーザーが claude-* モデルを要求した際に本プロバイダーも選択対象になります。",
+      "label": "Claude ルーティングプールに参加"
+    },
+    "modelRedirects": {
+      "label": "モデルリダイレクト設定",
+      "optional": "(任意)"
+    },
+    "modelWhitelist": {
+      "allowAll": "✓ すべてのモデルを許可(推奨)",
+      "desc": "このプロバイダーが処理できるモデルを制限します。既定では同タイプのすべてのモデルを処理できます。",
+      "label": "許可するモデル",
+      "moreModels": "+{count} 件 さらに表示",
+      "optional": "(任意)",
+      "selectedOnly": "選択した {count} 件のモデルのみ許可します。他のモデルはこのプロバイダーにルーティングされません。",
+      "title": "モデル許可リスト"
+    },
+    "preserveClientIp": {
+      "desc": "x-forwarded-for / x-real-ip を上流に渡します(実際の IP が露出する可能性)",
+      "help": "プライバシー保護のためデフォルトはオフ。上流側で端末 IP が必要な場合のみ有効化してください。",
+      "label": "クライアント IP を転送"
+    },
+    "providerType": {
+      "desc": "(スケジューリングに影響)",
+      "label": "プロバイダー種別",
+      "placeholder": "プロバイダー種別を選択"
+    },
+    "providerTypeDesc": "プロバイダーの API 形式を選択します。",
+    "providerTypeDisabledNote": "注: OpenAI Compatible は開発中のため、現在は使用できません",
+    "scheduleParams": {
+      "costMultiplier": {
+        "desc": "コスト計算の倍率。公式=1.0、20% 安い=0.8、20% 高い=1.2(小数4桁まで)",
+        "label": "コスト倍率",
+        "placeholder": "1.0"
+      },
+      "group": {
+        "desc": "グループタグ。ユーザーの providerGroup が一致する場合のみ利用可能。例: \"premium\" に設定すると providerGroup=\"premium\" のユーザーのみ対象",
+        "label": "プロバイダーグループ",
+        "placeholder": "例: premium, economy"
+      },
+      "priority": {
+        "desc": "値が小さいほど優先度が高くなります(0 が最も高い)。システムは最も高い優先度のプロバイダーのみから選択します。推奨: メイン=0、予備=1、緊急=2",
+        "label": "優先度",
+        "placeholder": "0"
+      },
+      "title": "スケジューリング設定",
+      "weight": {
+        "desc": "重み付きランダム。同一優先度内では重みが高いほど選ばれる確率が上がります。例 1:2:3 ≈ 16%:33%:50%",
+        "label": "重み",
+        "placeholder": "1"
+      }
+    },
+    "summary": {
+      "models": "許可モデル {count} 件",
+      "none": "未設定",
+      "redirects": "リダイレクト {count} 件"
+    },
+    "title": "ルーティング"
+  },
+  "timeout": {
+    "desc": "リクエストのタイムアウト時間を設定します。0 は無効を意味します",
+    "disableHint": "0に設定するとタイムアウトを無効にします(カナリアロールバックシナリオのみ、非推奨)",
+    "nonStreamingTotal": {
+      "core": "true",
+      "desc": "非ストリーミングリクエストの総タイムアウト、範囲60~1200秒、デフォルト600秒(10分)",
+      "label": "非ストリーミング総タイムアウト(秒)",
+      "placeholder": "600"
+    },
+    "streamingFirstByte": {
+      "core": "true",
+      "desc": "ストリーミングリクエストの初バイトタイムアウト、範囲1~120秒、デフォルト30秒",
+      "label": "ストリーミング初バイトタイムアウト(秒)",
+      "placeholder": "30"
+    },
+    "streamingIdle": {
+      "core": "true",
+      "desc": "ストリーミングリクエストのアイドルタイムアウト、範囲60~600秒、0で無効化(途中停止防止)",
+      "label": "ストリーミングアイドルタイムアウト(秒)",
+      "placeholder": "60"
+    },
+    "summary": "初回バイト: {streaming}s | ストリーム間隔: {idle}s | 非ストリーミング: {nonStreaming}s",
+    "title": "タイムアウト設定"
+  }
+}

+ 204 - 0
messages/ja/settings/providers/form/strings.json

@@ -0,0 +1,204 @@
+{
+  "addRedirect": "リダイレクトを追加",
+  "allowAllModels": "✓ すべてのモデルを許可 (推奨)",
+  "apiAddress": "API アドレス",
+  "apiAddressPlaceholder": "例: https://open.bigmodel.cn/api/anthropic",
+  "apiAddressRequired": "API アドレス *",
+  "apiKey": "APIキー",
+  "apiKeyCurrent": "現在のキー:",
+  "apiKeyLeaveEmpty": "(空欄のまま変更しない)",
+  "apiKeyLeaveEmptyDesc": "空欄の場合はキーを変更しません",
+  "apiKeyOptional": "現在のキーを保持する場合は空のままにしてください",
+  "apiKeyPlaceholder": "APIキーを入力",
+  "apiKeyRequired": "API キー *",
+  "baseUrl": "ベースURL",
+  "baseUrlPlaceholder": "例:https://open.bigmodel.cn/api/anthropic",
+  "baseUrlRequired": "プロバイダーURLを入力してください",
+  "circuitBreakerConfig": "サーキットブレーカー設定",
+  "circuitBreakerConfigSummary": "{failureThreshold} 回失敗 / {openDuration} 分間ブレーク / {successThreshold} 回成功で回復 / 各プロバイダー最大 {maxRetryAttempts} 回試行",
+  "circuitBreakerDesc": "連続失敗時に自動的にブレークして全体の品質を保護します",
+  "clearSearch": "検索をクリア",
+  "codexInstructions": "Codexインストラクション方針",
+  "codexInstructionsAuto": "自動 (推奨)",
+  "codexInstructionsDesc": "(スケジューリング方針を決定)",
+  "codexInstructionsForce": "公式を強制",
+  "codexInstructionsKeep": "元の値を保持",
+  "codexStrategyAutoDesc": "クライアントの instructions を透過し、400 エラー時は公式プロンプトで自動リトライします",
+  "codexStrategyAutoLabel": "自動 (推奨)",
+  "codexStrategyConfig": "Codex Instructions 戦略",
+  "codexStrategyConfigAuto": "自動 (推奨)",
+  "codexStrategyConfigForce": "公式を強制",
+  "codexStrategyConfigKeep": "元の値を保持",
+  "codexStrategyDesc": "Codex リクエストの instructions フィールドの扱いを制御します。上流ゲートウェイとの互換性に影響します",
+  "codexStrategyForceDesc": "公式の Codex CLI instructions を常に使用します (約 4000+ 文字)",
+  "codexStrategyForceLabel": "公式を強制",
+  "codexStrategyHint": "ヒント: 一部の厳格な Codex ゲートウェイ (例: 88code, foxcode) では公式 instructions が必要です。\"自動\" または \"公式を強制\" を選択してください",
+  "codexStrategyKeepDesc": "クライアントの instructions を常に透過し、自動リトライしません (柔軟なゲートウェイ向け)",
+  "codexStrategyKeepLabel": "元の値を保持",
+  "codexStrategySelect": "戦略の選択",
+  "collapseAll": "高度な設定をすべて折りたたむ",
+  "confirmAdd": "追加を確認",
+  "confirmAddPending": "追加中...",
+  "confirmUpdate": "更新を確認",
+  "confirmUpdatePending": "更新しています...",
+  "costMultiplier": "コスト乗数",
+  "costMultiplierDesc": "例: A (コスト 1.0x)、C (コスト 0.8x)",
+  "costMultiplierLabel": "コスト乗数",
+  "costMultiplierPlaceholder": "1.0",
+  "deleteButton": "削除",
+  "dialogDescription": "プロバイダーの詳細と高度な設定を構成します。",
+  "enabled": "有効",
+  "expandAll": "高度な設定をすべて展開",
+  "failureThreshold": "失敗閾値 (回)",
+  "failureThresholdDesc": "連続失敗が何回でブレークを発動するか",
+  "failureThresholdPlaceholder": "5",
+  "filterAllProviders": "すべてのプロバイダー",
+  "filterByType": "タイプでフィルタ",
+  "filterProvider": "プロバイダータイプでフィルタ",
+  "group": "グループ",
+  "groupPlaceholder": "例:premium, economy",
+  "joinClaudePool": "Claude スケジューリングプールに参加",
+  "joinClaudePoolDesc": "有効にすると、このプロバイダーは Claude タイプのプロバイダーとともに負荷分散スケジューリングに参加します",
+  "joinClaudePoolHelp": "モデルリダイレクト設定に claude-* モデルへのマッピングが含まれる場合にのみ利用可能です。有効にすると、ユーザーが claude-* モデルを要求した際にも、このプロバイダーがスケジューリング対象になります。",
+  "leaveEmpty": "無制限の場合は空のままにしてください",
+  "limit0Means": "0は無制限を意味します",
+  "limit5hLabel": "5時間支出上限 (USD)",
+  "limitAmount5h": "5時間支出上限 (USD)",
+  "limitAmount5hDesc": "例:プロバイダーBが$10制限、$9.8消費済み",
+  "limitAmountMonthly": "月間支出上限 (USD)",
+  "limitAmountWeekly": "週間支出上限 (USD)",
+  "limitConcurrent": "同時セッション数制限",
+  "limitConcurrentDesc": "例:プロバイダーC制限2、現在アクティブセッション数:2",
+  "limitConcurrentLabel": "同時セッション上限",
+  "limitMonthlyLabel": "月間支出上限 (USD)",
+  "limitPlaceholder0": "0 は無制限",
+  "limitPlaceholderUnlimited": "空欄は無制限",
+  "limitWeeklyLabel": "週間支出上限 (USD)",
+  "modelRedirects": "モデルリダイレクト",
+  "modelRedirectsAddNew": "新しいルールを追加",
+  "modelRedirectsCurrentRules": "現在のルール ({count})",
+  "modelRedirectsDesc": "Claudeモデルリクエストを他のサポートされるモデルにリダイレクトします",
+  "modelRedirectsEmpty": "リダイレクトルールがまだありません。ルールを追加すると、システムがリクエスト内のモデル名を自動で書き換えます。",
+  "modelRedirectsExists": "モデル \"{model}\" には既にリダイレクトルールがあります",
+  "modelRedirectsLabel": "モデルリダイレクト設定",
+  "modelRedirectsOptional": "(任意)",
+  "modelRedirectsSourceModel": "ユーザーが要求したモデル",
+  "modelRedirectsSourcePlaceholder": "例: claude-sonnet-4-5-20250929",
+  "modelRedirectsSourceRequired": "ソースモデル名は空にできません",
+  "modelRedirectsTargetModel": "実際に転送されるモデル",
+  "modelRedirectsTargetPlaceholder": "例: glm-4.6",
+  "modelRedirectsTargetRequired": "ターゲットモデル名は空にできません",
+  "modelWhitelist": "モデルホワイトリスト",
+  "modelWhitelistAllowAll": "すべての {type} モデルを許可",
+  "modelWhitelistAllowAllClause": "すべての Claude モデルを許可",
+  "modelWhitelistAllowAllOpenAI": "すべての OpenAI モデルを許可",
+  "modelWhitelistClear": "クリア",
+  "modelWhitelistDesc": "このプロバイダーが処理できるモデルを制限します。既定では、同タイプのすべてのモデルを処理できます。",
+  "modelWhitelistLabel": "許可するモデル",
+  "modelWhitelistLoading": "読み込み中...",
+  "modelWhitelistManualAdd": "モデルを手動追加",
+  "modelWhitelistManualDesc": "価格表に限定せず、任意のモデル名を追加できます",
+  "modelWhitelistManualPlaceholder": "モデル名を入力 (例: gpt-5-turbo)",
+  "modelWhitelistNotFound": "モデルが見つかりません",
+  "modelWhitelistSearchPlaceholder": "モデル名を検索...",
+  "modelWhitelistSelectAll": "すべて選択 ({count})",
+  "modelWhitelistSelected": "{count} 件選択済み",
+  "modelWhitelistSelectedOnly": "選択した {count} 件のモデルのみ許可します。他のモデルへのリクエストはこのプロバイダーにルーティングされません。",
+  "namePlaceholder": "プロバイダー名を入力",
+  "openDuration": "ブレーク時間 (分)",
+  "openDurationDesc": "どれくらいで自動的に半開状態に移行するか",
+  "openDurationPlaceholder": "30",
+  "priority": "優先度",
+  "priorityDesc": "同じ優先度内では、コスト乗数の低い順でソートされます",
+  "priorityLabel": "優先度",
+  "priorityPlaceholder": "0",
+  "providerGroupDesc": "プロバイダーグループタグ。ユーザーの providerGroup が一致する場合のみこのプロバイダーを利用できます。例: \"premium\" に設定すると providerGroup=\"premium\" のユーザーのみ利用可能です",
+  "providerGroupLabel": "プロバイダーグループ",
+  "providerGroupPlaceholder": "例: premium, economy",
+  "providerName": "プロバイダー名",
+  "providerNamePlaceholder": "例: 智譜",
+  "providerNameRequired": "プロバイダー名 *",
+  "providerType": "プロバイダータイプ",
+  "providerTypeDesc": "プロバイダーの API フォーマット種別を選択します。",
+  "providerTypeDisabledNote": "注: Gemini CLI と OpenAI Compatible タイプは開発中のため、現在は利用できません",
+  "proxy": "プロキシ",
+  "proxyAddressFormats": "対応形式:",
+  "proxyAddressLabel": "プロキシアドレス",
+  "proxyAddressOptional": "(任意)",
+  "proxyAddressPlaceholder": "例: http://proxy.example.com:8080 または socks5://127.0.0.1:1080",
+  "proxyConfig": "プロキシ設定",
+  "proxyConfigDesc": "プロバイダーへの接続性を向上させるためにプロキシサーバーを設定します (HTTP、HTTPS、SOCKS4、SOCKS5 に対応)",
+  "proxyConfigNone": "未設定",
+  "proxyConfigSummary": "プロキシ設定済み",
+  "proxyConfigSummaryFallback": " (フォールバック有効)",
+  "proxyConfigured": "プロキシが設定されています",
+  "proxyFallback": "プロキシ失敗時のフォールバック",
+  "proxyFallbackDesc": "プロキシ失敗時に直接接続にフォールバックします",
+  "proxyFallbackLabel": "プロキシ失敗時に直接接続へフォールバック",
+  "proxyNotConfigured": "未設定",
+  "proxyTestButton": "接続をテスト",
+  "proxyTestDesc": "設定したプロキシ経由でプロバイダー URL へのアクセスをテストします (HEAD リクエストを使用し、クォータは消費しません)",
+  "proxyTestFailed": "接続失敗",
+  "proxyTestFillUrl": "先にプロバイダー URL を入力してください",
+  "proxyTestLabel": "接続テスト",
+  "proxyTestNetworkError": "ネットワークエラー: {error}",
+  "proxyTestProxyError": "プロキシエラー: {error}",
+  "proxyTestResponseTime": "応答時間: {time}",
+  "proxyTestResultConnectionMethod": "接続方法: {via}",
+  "proxyTestResultConnectionMethodDirect": "直接",
+  "proxyTestResultConnectionMethodProxy": "プロキシ",
+  "proxyTestResultErrorType": "エラー種別: {type}",
+  "proxyTestResultFailed": "接続失敗",
+  "proxyTestResultMessage": "{message}",
+  "proxyTestResultResponseTime": "応答時間: {time}ms",
+  "proxyTestResultStatusCode": "ステータスコード: {code}",
+  "proxyTestResultSuccess": "接続成功 {via}",
+  "proxyTestStatusCode": "| ステータスコード: {code}",
+  "proxyTestSuccess": "接続成功",
+  "proxyTestTesting": "テスト中...",
+  "proxyTestTimeout": "接続がタイムアウトしました (5秒)。次を確認してください:\n1. プロキシサーバーに接続できるか\n2. プロキシのアドレスとポートが正しいか\n3. プロキシの認証情報が正しいか",
+  "proxyTestViaDirect": "(直接)",
+  "proxyTestViaProxy": "(プロキシ経由)",
+  "proxyUrl": "プロキシアドレス",
+  "proxyUrlPlaceholder": "例:http://proxy.example.com:8080 または socks5://127.0.0.1:1080",
+  "rateLimitConfig": "レート制限設定",
+  "rateLimitConfigNone": "無制限",
+  "rateLimitConfigSummary": "5h: ${fiveHour}, 週: ${weekly}, 月: ${monthly}, 同時: {concurrent}",
+  "remark": "備考",
+  "remarkPlaceholder": "オプション:説明を追加...",
+  "removeRedirect": "リダイレクトを削除",
+  "routingConfig": "ルーティング設定",
+  "routingConfigNone": "未設定",
+  "routingConfigSummary": "モデル許可リスト {models} 件、リダイレクト {redirects} 件",
+  "scheduleParams": "スケジューリングパラメータ",
+  "searchClear": "検索をクリア",
+  "searchPlaceholder": "プロバイダー名、URL、備考で検索...",
+  "selectProviderType": "プロバイダータイプを選択",
+  "sort": "プロバイダーをソート",
+  "sortByCost": "コスト順",
+  "sortByCreated": "作成日順 (新-旧)",
+  "sortByName": "名前順 (A-Z)",
+  "sortByPriority": "優先度順 (高-低)",
+  "sortByWeight": "重み順 (高-低)",
+  "sourceModel": "ソースモデル名",
+  "sourceModelPlaceholder": "例:claude-sonnet-4-5-20250929",
+  "sourceModelRequired": "ソースモデル名は空にできません",
+  "successThreshold": "回復閾値 (回)",
+  "successThresholdDesc": "半開状態で何回成功したら完全に回復するか",
+  "successThresholdPlaceholder": "2",
+  "targetModel": "ターゲットモデル名",
+  "targetModelPlaceholder": "例:glm-4.6",
+  "targetModelRequired": "ターゲットモデル名は空にできません",
+  "testProxy": "接続をテスト",
+  "testProxyFailed": "プロキシテストに失敗しました",
+  "testProxyFailedError": "接続テスト失敗:",
+  "testProxySuccess": "プロキシ接続成功",
+  "validUrlRequired": "有効な API アドレスを入力してください",
+  "websiteUrlDesc": "プロバイダー公式サイト URL (管理画面へのクイックリンク)",
+  "websiteUrlInvalid": "有効なプロバイダー公式サイト URL を入力してください",
+  "websiteUrlPlaceholder": "https://example.com",
+  "weight": "重み",
+  "weightDesc": "加重ランダム確率。同じ優先度内では、重みが高いほど選択される確率が高くなります。",
+  "weightLabel": "重み",
+  "weightPlaceholder": "1"
+}

+ 4 - 0
messages/ja/settings/providers/form/success.json

@@ -0,0 +1,4 @@
+{
+  "created": "プロバイダーを追加しました",
+  "createdDesc": "「{name}」を追加しました"
+}

+ 4 - 0
messages/ja/settings/providers/form/title.json

@@ -0,0 +1,4 @@
+{
+  "create": "プロバイダーを追加",
+  "edit": "プロバイダーを編集"
+}

+ 4 - 0
messages/ja/settings/providers/form/url.json

@@ -0,0 +1,4 @@
+{
+  "label": "API アドレス *",
+  "placeholder": "例: https://open.bigmodel.cn/api/anthropic"
+}

+ 9 - 0
messages/ja/settings/providers/form/urlPreview.json

@@ -0,0 +1,9 @@
+{
+  "copy": "コピー",
+  "copyFailed": "コピーに失敗しました",
+  "copySuccess": "{name} をクリップボードにコピーしました",
+  "duplicatePath": "重複パス検出",
+  "invalidUrl": "無効なURL形式",
+  "invalidUrlDesc": "有効なHTTP/HTTPSアドレスを入力してください",
+  "title": "URL結合プレビュー"
+}

+ 5 - 0
messages/ja/settings/providers/form/websiteUrl.json

@@ -0,0 +1,5 @@
+{
+  "desc": "管理ページへのクイックアクセス用",
+  "label": "プロバイダー公式サイト",
+  "placeholder": "https://example.com"
+}

+ 120 - 0
messages/ja/settings/providers/guide.json

@@ -0,0 +1,120 @@
+{
+  "after": "フィルタ後:",
+  "before": "フィルタ前:",
+  "bestPracticesConcurrent": "• 同時実行制御: プロバイダー API 制限に合わせてセッションの同時数を設定",
+  "bestPracticesCost": "• コスト乗数: 公式=1.0、自前ホストは 0.8-1.2 を設定可能",
+  "bestPracticesLimit": "• 上限設定: 予算に合わせて 5h / 7d / 30d の上限を設定",
+  "bestPracticesPriority": "• 優先度設定: メインのプロバイダー=0、バックアップ=1-3",
+  "bestPracticesTitle": "ベストプラクティス",
+  "bestPracticesWeight": "• 重み設定: 容量に応じて重みを設定 (容量が大きいほど重みも大きい)",
+  "circuitBreaker": "サーキットブレーカーチェック",
+  "circuitBreakerOpen": "Aはフィルタされました、残り:B、C、D",
+  "circuitBreakerRecovery": "Aは60秒後に半開状態に自動復帰します",
+  "circuitBreakerRecovery5h": "5時間スライディングウィンドウ後に自動復帰",
+  "costOptimize": "2. コスト最適化: 同一優先度内では、コスト乗数が低いほど選択確率が高くなります",
+  "costSort": "コストベースのソートフォールバック",
+  "costSortExample": "すべてのプロバイダー: A (default)、B (premium)、C (premium)、D (economy)",
+  "costSortProb": "より安いCがより高い選択確率を持ちます",
+  "costSortResult": "ソート後: C (0.8x)、A (1.0x)",
+  "decision": "判断:",
+  "group": "ユーザーグループフィルタリング",
+  "groupDesc": "ユーザーがプロバイダーグループを指定した場合、システムはそのグループから優先的に選択します",
+  "groupDowngrade": "警告をログに記録し、グローバルプロバイダープールから選択",
+  "groupExample": "ユーザーは providerGroup = 'premium' を設定しました",
+  "groupFallback": "グループに利用可能なプロバイダーがない場合は、すべてのプロバイダーにフォールバック",
+  "groupFiltered": "AとCのみから選択、BとDはフィルタされます",
+  "groupUnavailable": "ユーザーグループ'vip'のすべてのプロバイダーが無効または制限超過です",
+  "health": "健全性フィルタリング (サーキットブレーカー + レート制限)",
+  "healthCheck": "Bが有効で健全かをチェック",
+  "healthCheckAmountLimit": "支出上限をチェック (5h, 7d, 30d)",
+  "healthCheckAmountLimitExample": "プロバイダー B の 5h 上限 $10、消費 $9.8",
+  "healthCheckCircuit": "プロバイダー A 5回失敗、サーキットブレーカー: オープン",
+  "healthCheckConcurrent": "現在のアクティブセッション数が上限を超えていないかをチェック",
+  "healthCheckConcurrentExample": "プロバイダー C 同時制限 2、現在アクティブ 2 セッション",
+  "healthFilter": "3. ヘルスフィルタ: サーキットブレーカー中または上限超過のプロバイダーを自動でスキップします",
+  "healthFiltered": "B を除外 (上限に接近)、残り: C、D",
+  "healthFiltered2": "C を除外 (満杯)、残り: D",
+  "history": "リクエスト履歴をチェック",
+  "historyDesc": "この API キーが過去 10 秒間に使用したプロバイダーをクエリします",
+  "priority": "優先度階層化",
+  "priorityExample": "異なる優先度を持つ4つのプロバイダーが有効です",
+  "priorityFirst": "1. 優先度優先: 最優先 (数値が最小) のプロバイダーからのみ選択します",
+  "priorityResult": "最優先 (0) のプロバイダーに絞り込み: A、C",
+  "priorityStep": "システムは優先度でフィルタし、最高優先度のプロバイダーのみを選択します",
+  "randomResult": "最終的に C がランダムに選択されました",
+  "randomSelect": "加重ランダム",
+  "reset": "サーキットブレーカーを手動リセット",
+  "resetSuccess": "サーキットブレーカーがリセットされました",
+  "scenario1Desc": "システムはまず優先度でフィルタし、最優先プロバイダーのみから選択します",
+  "scenario1Step1": "初期状態",
+  "scenario1Step1After": "最優先 (0) のプロバイダーに絞り込み: A、C",
+  "scenario1Step1Before": "プロバイダー A (優先度 0)、B (優先度 1)、C (優先度 0)、D (優先度 2)",
+  "scenario1Step1Decision": "A と C のみから選択し、B と D は除外されます",
+  "scenario1Step1Desc": "優先度が異なる4つのプロバイダーが有効です",
+  "scenario1Step2": "コストソート",
+  "scenario1Step2After": "ソート後: C (0.8x)、A (1.0x)",
+  "scenario1Step2Before": "A (コスト 1.0x)、C (コスト 0.8x)",
+  "scenario1Step2Decision": "より安い C の方が選択確率が高くなります",
+  "scenario1Step2Desc": "同一優先度内では、コスト乗数の低い順にソートします",
+  "scenario1Step3": "加重ランダム",
+  "scenario1Step3After": "C の確率 75%、A の確率 25%",
+  "scenario1Step3Before": "C (重み 3)、A (重み 1)",
+  "scenario1Step3Decision": "最終的に C がランダムに選択されました",
+  "scenario1Step3Desc": "重みでランダム選択し、重みが大きいほど確率が高くなります",
+  "scenario1Title": "優先度階層化",
+  "scenario2Desc": "ユーザーがプロバイダーグループを指定した場合、システムはそのグループから優先的に選択します",
+  "scenario2Step1": "ユーザーグループを確認",
+  "scenario2Step1After": "'premium' グループに絞り込み: B、C",
+  "scenario2Step1Before": "すべてのプロバイダー: A (default)、B (premium)、C (premium)、D (economy)",
+  "scenario2Step1Decision": "B と C のみから選択します",
+  "scenario2Step1Desc": "ユーザーは providerGroup = 'premium' を設定しました",
+  "scenario2Step2": "グループフォールバック",
+  "scenario2Step2After": "有効なすべてのプロバイダーにフォールバック: A、B、C、D",
+  "scenario2Step2Before": "ユーザーグループ'vip'のすべてのプロバイダーが無効または制限超過です",
+  "scenario2Step2Decision": "警告をログに記録し、グローバルプロバイダープールから選択します",
+  "scenario2Step2Desc": "グループに利用可能なプロバイダーがない場合は、すべてのプロバイダーにフォールバック",
+  "scenario2Title": "ユーザーグループフィルタリング",
+  "scenario3Desc": "システムはサーキットブレーカー中または上限超過のプロバイダーを自動で除外します",
+  "scenario3Step1": "サーキットブレーカーチェック",
+  "scenario3Step1After": "A を除外、残り: B、C、D",
+  "scenario3Step1Before": "プロバイダー A 5回失敗、サーキットブレーカー: オープン",
+  "scenario3Step1Decision": "A は 60 秒後に半開状態へ自動復帰します",
+  "scenario3Step1Desc": "5回連続で失敗するとサーキットブレーカーがオープンし、60秒間利用できません",
+  "scenario3Step2": "金額レート制限",
+  "scenario3Step2After": "B を除外 (上限に接近)、残り: C、D",
+  "scenario3Step2Before": "プロバイダー B の 5h 上限 $10、消費 $9.8",
+  "scenario3Step2Decision": "5時間スライディングウィンドウ後に自動復帰",
+  "scenario3Step2Desc": "支出が上限 (5h, 7d, 30d) を超えていないか確認します",
+  "scenario3Step3": "同時セッション制限",
+  "scenario3Step3After": "C を除外 (満杯)、残り: D",
+  "scenario3Step3Before": "プロバイダー C 同時制限 2、現在アクティブ 2 セッション",
+  "scenario3Step3Decision": "セッション期限切れ後に自動解放 (5分)",
+  "scenario3Step3Desc": "現在のアクティブセッション数が設定された同時上限を超えていないか確認します",
+  "scenario3Title": "ヘルスフィルタ (サーキットブレーカー + レート制限)",
+  "scenario4Desc": "連続したチャットでは Claude のコンテキストキャッシュを活用し、同じプロバイダーを優先して再利用します",
+  "scenario4Step1": "リクエスト履歴を確認",
+  "scenario4Step1After": "B が有効で健全かをチェック",
+  "scenario4Step1Before": "最後のリクエストはプロバイダー B を使用しました",
+  "scenario4Step1Decision": "B は利用可能なら直接再利用し、ランダム選択をスキップします",
+  "scenario4Step1Desc": "この API キーが過去 10 秒間に使用したプロバイダーをクエリします",
+  "scenario4Step2": "再利用の無効化",
+  "scenario4Step2After": "通常の選択フローに戻ります",
+  "scenario4Step2Before": "前回使用したプロバイダー B は無効またはサーキットオープン状態です",
+  "scenario4Step2Decision": "他の利用可能なプロバイダーから選択",
+  "scenario4Step2Desc": "前回使用したプロバイダーが利用できない場合は再選択します",
+  "scenario4Title": "セッション再利用メカニズム",
+  "scenariosTitle": "インタラクティブなシナリオデモ",
+  "session": "セッション再利用メカニズム",
+  "sessionDesc": "前回使用したプロバイダーが利用できない場合は再選択します",
+  "sessionExample": "最後のリクエストはプロバイダー B を使用しました",
+  "sessionExpired": "セッションは期限切れ (5分) 後に自動的に解放されます",
+  "sessionFallback": "他の利用可能なプロバイダーから選択",
+  "sessionLastUsed": "B は利用可能、直接再利用、ランダム選択をスキップ",
+  "sessionReuse": "4. セッション再利用: 連続したチャットでは同じプロバイダーを再利用し、コンテキストコストを節約します",
+  "sessionUnavailable": "前回使用したプロバイダー B は無効またはサーキットオープン状態です",
+  "step": "ステップ",
+  "title": "基本原則",
+  "weight": "重みに基づく加重ランダム選択",
+  "weightCalc": "Cは75%の選択確率、Aは25%",
+  "weightExample": "C (重み 3)、A (重み 1)"
+}

+ 12 - 0
messages/ja/settings/providers/inlineEdit.json

@@ -0,0 +1,12 @@
+{
+  "cancel": "キャンセル",
+  "costMultiplierInvalid": "0以上の数値を入力してください",
+  "costMultiplierLabel": "コスト倍率",
+  "priorityInvalid": "0 以上の整数を入力してください",
+  "priorityLabel": "優先度",
+  "save": "保存する",
+  "saveFailed": "保存に失敗しました",
+  "saveSuccess": "保存に成功しました",
+  "weightInvalid": "1〜100 の整数を入力してください",
+  "weightLabel": "重み"
+}

+ 37 - 0
messages/ja/settings/providers/list.json

@@ -0,0 +1,37 @@
+{
+  "cancelButton": "キャンセル",
+  "circuitBroken": "遮断中",
+  "clipboardUnavailable": "この環境ではクリップボードを使用できません。手動でコピーしてください。",
+  "confirmDeleteMessage": "プロバイダー \"{name}\" を削除してもよろしいですか?この操作は元に戻せません。",
+  "confirmDeleteTitle": "プロバイダーの削除を確認しますか?",
+  "copyFailed": "コピーに失敗しました",
+  "costMultiplier": "コスト倍率",
+  "deleteButton": "削除",
+  "deleteError": "操作中にエラーが発生しました",
+  "deleteFailed": "削除に失敗しました",
+  "deleteSuccess": "削除に成功しました",
+  "deleteSuccessDesc": "プロバイダー \"{name}\" が削除されました",
+  "getKeyFailed": "キーの取得に失敗しました",
+  "keyCopied": "キーがクリップボードにコピーされました",
+  "keyLoading": "読み込み中...",
+  "officialWebsite": "公式",
+  "priority": "優先度",
+  "resetCircuitFailed": "サーキットブレーカーのリセットに失敗しました",
+  "resetCircuitSuccess": "サーキットブレーカーがリセットされました",
+  "resetCircuitSuccessDesc": "プロバイダー \"{name}\" のサーキットブレーカーステータスがクリアされました",
+  "resetUsageFailed": "総用量のリセットに失敗しました",
+  "resetUsageSuccess": "総用量をリセットしました",
+  "resetUsageSuccessDesc": "プロバイダー \"{name}\" の総用量をリセットしました",
+  "resetUsageTitle": "総用量をリセット",
+  "statusDisabled": "無効",
+  "statusEnabled": "有効",
+  "todayUsageCount": "{count} 回",
+  "todayUsageLabel": "本日の使用量",
+  "toggleFailed": "切り替えに失敗しました",
+  "toggleSuccess": "プロバイダーが{status}になりました",
+  "toggleSuccessDesc": "プロバイダー \"{name}\" のステータスが更新されました",
+  "unknownError": "不明なエラー",
+  "viewFullKey": "完全な API キーを表示",
+  "viewFullKeyDesc": "安全に保管し、他人と共有しないでください",
+  "weight": "重み"
+}

+ 9 - 0
messages/ja/settings/providers/schedulingDialog.json

@@ -0,0 +1,9 @@
+{
+  "after": "後:",
+  "before": "前:",
+  "decision": "決定:",
+  "description": "システムが高可用性とコスト最適化のために上流プロバイダーをインテリジェントに選択する方法を理解する",
+  "step": "ステップ",
+  "title": "プロバイダースケジューリングルール",
+  "triggerButton": "スケジューリングルール"
+}

+ 7 - 0
messages/ja/settings/providers/search.json

@@ -0,0 +1,7 @@
+{
+  "clear": "検索をクリア",
+  "found": "{count}件のプロバイダーが見つかりました",
+  "notFound": "一致するプロバイダーが見つかりません",
+  "placeholder": "プロバイダー名、URL、メモを検索...",
+  "showing": "{filtered} / {total} プロバイダーを表示"
+}

+ 5 - 0
messages/ja/settings/providers/section.json

@@ -0,0 +1,5 @@
+{
+  "description": "上流プロバイダーの支出制限とセッション並行制限を設定します。空のままにすると無制限です。",
+  "leaderboard": "プロバイダーランキング",
+  "title": "プロバイダー管理"
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است