hermes-agent/locales/zh-hant.yaml
Teknium c39168453d
feat(i18n): localize all gateway commands + web dashboard, add 8 new locales (16 total) (#22914)
* feat(i18n): localize /model command output

Reported by @tianma8888: when Chinese users run /model, the labels
("Provider:", "Context:", "_session only_", etc.) are still English.
This routes the static prose through the existing i18n catalog so it
follows display.language / HERMES_LANGUAGE.

Changes:
- locales/{en,zh,ja,de,es,fr,tr,uk}.yaml: add 17 keys under
  gateway.model.* covering switched/provider/context/max_output/cost/
  capabilities/prompt_caching/warning/saved_global/session_only_hint/
  current_label/current_tag/more_models_suffix/usage_*.
- gateway/run.py _handle_model_command: replace hardcoded f-strings in
  the picker callback, the text-list fallback, and the direct-switch
  confirmation block with t("gateway.model.<key>", ...).

What stays English:
- model IDs, provider slugs, capability strings, cost figures, and the
  "[Note: model was just switched...]" prepended to the model's next
  prompt (LLM-facing, not user-facing).
- The two slightly-different session-only hints unify on a single key
  with the em-dash phrasing.

Validation: tests/agent/test_i18n.py 27/27 passing (parity contract
holds), tests/gateway/ -k 'model or i18n' 74/74 passing.

* feat(i18n): localize all gateway slash command outputs

Expands the i18n catalog from 7 strings to 234 keys across 35 gateway
slash command handlers, so non-English users see localized output for
\`/profile\`, \`/status\`, \`/help\`, \`/personality\`, \`/voice\`, \`/reset\`,
\`/agents\`, \`/restart\`, \`/commands\`, \`/goal\`, \`/retry\`, \`/undo\`,
\`/sethome\`, \`/title\`, \`/yolo\`, \`/background\`, \`/approve\`, \`/deny\`,
\`/insights\`, \`/debug\`, \`/rollback\`, \`/reasoning\`, \`/fast\`,
\`/verbose\`, \`/footer\`, \`/compress\`, \`/topic\`, \`/kanban\`,
\`/resume\`, \`/branch\`, \`/usage\`, \`/reload-mcp\`, \`/reload-skills\`,
\`/update\`, \`/stop\` (plus the \`/model\` block already added in the
previous commit).

Reported by @tianma8888 — Chinese users want command output prose in
their language, not just the labels we already had.

Translations are hand-written for all 8 supported locales (en, zh, ja,
de, es, fr, tr, uk), matching each catalog's existing style: full-width
punctuation in zh, em-dashes in zh/ja/uk, French spaced colons,
German noun capitalization, etc.

What stays English (unchanged):
- Identifiers/values: model IDs, file paths, profile names, session IDs,
  command flag names like --global, URLs, config keys.
- Backtick code spans: \`/foo\`, \`config.yaml\`.
- Log messages (logger.info/warning/error).
- LLM-facing system notes prepended to next prompt (e.g. [Note: model
  was just switched...]).
- Strings produced by external modules (gateway_help_lines,
  format_gateway, manual_compression_feedback) — those have their
  own surfaces.

New shared keys for cross-handler boilerplate:
- gateway.shared.session_db_unavailable (5 call sites: branch, title,
  resume, topic, _disable_telegram_topic_mode_for_chat)
- gateway.shared.session_not_found (1 site)
- gateway.shared.warn_passthrough (2 sites in /title's f"⚠️ {e}" pattern)

YAML gotcha fixed: \`yolo.on\` and \`yolo.off\` were originally written
unquoted, which YAML 1.1 parses as boolean True/False keys. Renamed to
\`yolo.enabled\` / \`yolo.disabled\` for both safety and clarity.

Test fix: tests/agent/test_i18n.py::test_t_missing_key_in_non_english_falls_back_to_english
now resets the catalog cache on teardown, so the fake "foo: English Foo"
locale doesn't poison the module-level cache for subsequent tests in
the same xdist worker. (Without this, every gateway slash command test
that shares a worker with the i18n suite would see the fake catalog.)

Validation:
- tests/agent/test_i18n.py: 27/27 (parity contract — every key in every
  locale, matching placeholder tokens).
- tests/gateway/: 5077 passed, 0 failed (full gateway suite).
- 180 t() call sites added across 35 handlers; 1872 catalog entries
  total (234 keys × 8 locales).

* feat(i18n): add 8 new locales — af, ko, it, ga, zh-hant, pt, ru, hu

Expands the static-message catalog from 8 → 16 languages, each with full
270-key parity against the English source-of-truth.  Every locale now
covers the same surface PR #22914 added: approval prompts plus all 35
gateway slash command outputs.

New locales:
- af  Afrikaans      (community ask in #21961 by @GodsBoy; PRs #21962, #21970)
- ko  Korean         (PRs #20297 by @tmdgusya, #22285 by @project820)
- it  Italian        (PR #20371 by @leprincep35700)
- ga  Irish/Gaeilge  (PR #20962 by @ryanmcc09-dot)
- zh-hant Traditional Chinese (PRs #20523 by @jackey8616, #13140 by @anomixer)
- pt  Portuguese     (PRs #20443 by @pedroborges, #15737 by @carloshenriquecarniatto, #22063 by @Magaav)
- ru  Russian        (PR #22770 by @DrMaks22)
- hu  Hungarian      (PR #22336 by @lunasec007)

Each locale uses native-quality translations matching the existing tone
and conventions of the older 8 locales:
- zh-hant uses 繁體 characters with TW/HK technical vocabulary (軟體
  not 软件, 連線 not 连接, 設定 not 设置, 訊息 not 消息, 工作階段 not 会话, 程式
  not 程序, 預設 not 默认, 伺服器 not 服务器), full-width punctuation 「:()」.
- ko uses formal 합니다체 (습니다/합니다) register throughout.
- pt uses European Portuguese as baseline with neutral PT/BR vocabulary
  where possible.
- ga uses standard An Caighdeán Oifigiúil; English loanwords retained
  for tech terms without good Irish equivalents (gateway, API, JSON).
- All preserve {placeholder} tokens, backtick code spans, slash commands,
  brand names (Hermes, MCP, TTS, YOLO, OpenAI, Telegram, etc.), and emoji.

Aliases added in agent/i18n.py:
- af-za, Afrikaans → af
- ko-kr, Korean, 한국어 → ko
- it-it, italiano → it
- ga-ie, Irish, Gaeilge → ga
- zh-tw, zh-hk, zh-mo, traditional-chinese → zh-hant (note: zh-tw used to
  alias to zh; now aliases to its own zh-hant catalog)
- zh-cn, zh-hans, zh-sg → zh (unchanged from before)
- pt-pt, pt-br, brazilian, portuguese → pt
- ru-ru, Russian, русский → ru
- hu-hu, Magyar → hu

The zh-tw alias re-routing is intentional: previously typing 'zh-TW' got
the Simplified Chinese catalog (wrong vocabulary for Taiwan/HK users).
Now those users get the proper Traditional Chinese catalog.

Validation:
- tests/agent/test_i18n.py: 43/43 (parity contract holds for all 16
  languages × 270 keys = 4320 catalog entries, with matching placeholder
  tokens).
- E2E alias resolution verified for all 19 alias inputs (Afrikaans, ko-KR,
  한국어, italiano, Gaeilge, zh-TW, zh-HK, traditional-chinese, pt-BR,
  brazilian, Magyar, etc.).
- tests/gateway/: 5198 passed (3 pre-existing TTS routing failures
  unrelated to i18n).

Credit to all contributors whose PRs surfaced these language requests.
Their original PRs may now be closed as superseded with credit.

* feat(dashboard-i18n): add 14 web dashboard locales matching the static catalog

Brings the React dashboard (web/src/) up to the same 16-language
coverage the static catalog already has after the previous commits in
this PR. The Translations interface is TypeScript-typed, so every new
locale must provide every key — tsc -b is the parity guard.

Languages added (each is a complete 429-line locale file):
- af  Afrikaans
- ja  Japanese        (PR #22513 by @snuffxxx surfaced this)
- de  German          (PR #21749 by @mag1art)
- es  Spanish         (PR #21749)
- fr  French          (PRs #21749, #10310 by @foXaCe)
- tr  Turkish
- uk  Ukrainian
- ko  Korean          (PRs #21749, #18894 by @ovstng, #22285 by @project820)
- it  Italian
- ga  Irish (Gaeilge)
- zh-hant Traditional Chinese (PR #13140 by @anomixer)
- pt  Portuguese      (PRs #22063 by @Magaav, #22182 by @wesleysimplicio, #15737 by @carloshenriquecarniatto)
- ru  Russian         (PRs #21749, #22770 by @DrMaks22)
- hu  Hungarian       (PR #22336 by @lunasec007)

Each translation covers all 15 namespaces with full key parity vs en.ts,
preserves every {placeholder} token verbatim, keeps identifiers
untranslated (brand names, file paths, cron expressions, code spans),
translates the language.switchTo tooltip into the target language, and
matches existing tone conventions (zh-hant uses TW/HK vocab; ja uses
formal desu/masu; ko uses formal seumnida register; ga uses An
Caighdean Oifigiuil with English loanwords for tech vocab without good
Irish equivalents).

Plumbing:
- web/src/i18n/types.ts: Locale union expanded to all 16 codes.
- web/src/i18n/context.tsx: imports all 16 catalogs; exports
  LOCALE_META (endonym + flag per locale); isLocale() type guard.
- web/src/i18n/index.ts: re-export LOCALE_META.
- web/src/components/LanguageSwitcher.tsx: replaced two-state EN-ZH
  toggle with a click-to-open dropdown listing all 16 languages.

Note: zh-hant.ts exports zhHant (camelCase) since hyphen is invalid in
a JS identifier; the canonical 'zh-hant' string keys it in TRANSLATIONS.

Validation:
- npx tsc -b: 0 errors. Every locale satisfies Translations.
- npm run build (tsc + vite production): green, 2062 modules.
- Each locale file is exactly 429 lines.

Out of scope: plugin dashboards (kanban/achievements ship as prebuilt
bundles with no source in repo); Docusaurus docs (separate surface);
TUI (no i18n yet).

* feat(plugin-i18n): localize achievements + kanban plugin dashboards across all 16 locales

Brings the two shipped plugin dashboards (hermes-achievements, kanban)
under the same i18n umbrella as the core dashboard PR #22914 just
established.  Both bundles now read user-facing strings from the host's
i18n catalog via SDK.useI18n() instead of hardcoded English.

## Approach

Plugin dashboards ship as prebuilt IIFE bundles in
plugins/<name>/dashboard/dist/index.js — no build step, no source in
repo (upstream-authored, vendored as compiled JS).  Earlier contributor
PRs (#22594, #22595, #18747) tried direct edits but didn't actually
wire the bundles to read translations.

This change does the wiring properly:

1.  Each bundle gets a useI18n shim at IIFE scope:
        const useI18n = SDK.useI18n
          || function () { return { t: { kanban: null }, locale: "en" }; };
    Older host SDKs without useI18n still load the bundle and render
    English fallbacks.

2.  A small tx(t, path, fallback, vars) helper resolves dotted keys
    under the plugin's namespace (t.kanban.* or t.achievements.*) and
    interpolates {placeholder} tokens.

3.  Every React component starts with const { t } = useI18n() and
    each user-visible string is wrapped in tx(t, "key", "English fallback").
    Helpers called outside React components (window.prompt callers,
    constants used during init) take t as a parameter.

4.  Top-level constants that were English dictionaries (COLUMN_LABEL,
    COLUMN_HELP, DESTRUCTIVE_TRANSITIONS, DIAGNOSTIC_EVENT_LABELS in
    kanban) become getColumnLabel(t, status)-style functions backed by
    FALLBACK_* dictionaries.

## Translations added

Two new top-level namespaces added to the dashboard's TypeScript-typed
Translations interface:

- achievements: ~70 keys covering the hero, scan banner, achievement
  card, share dialog, stats, filters, and empty states.
- kanban: ~145 keys covering the board, columns (with nested
  columnLabels and columnHelp sub-dicts), card detail panel,
  bulk-actions toolbar, dependency editor, board switcher, and
  diagnostic callouts.

Each key is provided across all 16 supported locales:
en, zh, zh-hant, ja, de, es, fr, tr, uk, af, ko, it, ga, pt, ru, hu.

Total new translation entries: ~3,440 (215 keys × 16 locales).

## What stays English (deliberate)

- API paths, CSS class names, data-* attributes, JSON keys, regex
  strings, URLs, file paths (~/.hermes/kanban.db, boards/_archived/).
- State identifier strings used as lookup keys (triage / todo / ready /
  running / blocked / done / archived) — labels translate, key strings
  don't.
- The PNG share-card text rendered to canvas in the achievements
  ShareDialog (HERMES AGENT watermark, UNLOCKED stamp, tier names) —
  these become part of a globally-shared image and stay English.
- localStorage keys (hermes.kanban.selectedBoard).
- Brand names (Kanban, Hermes, WebSocket, Nous Research).

## Contributor credit

PR #22594 by @02356abc and PR #22595 by @02356abc supplied the
en + zh kanban namespace skeleton (145 keys); used as the en source-
of-truth in this commit and translated to the other 14 locales.

PR #18747 by @laolaoshiren first surfaced the achievements
localization request.

## Validation

- npx tsc -b: 0 errors. All 16 locale .ts files satisfy the
  Translations type with full key parity.
- npm run build (tsc + vite production build): green, 2062 modules,
  1.56MB JS / 95KB CSS, ~2.5s build.
- node --check on both plugin bundles: parse cleanly.
- 126 tx() call sites in kanban, 46 in achievements.

## Out of scope

- TUI (ui-tui/) has no i18n infrastructure yet.
- Docusaurus docs (website/i18n/) — already had zh-Hans; expanding
  is a separate translation workstream (Thai / Korean / Hindi PRs).
2026-05-10 07:14:14 -07:00

350 lines
23 KiB
YAML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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

# Hermes 靜態訊息目錄 -- 繁體中文(台灣/香港)
# See locales/en.yaml for the source of truth; keep keys in sync.
approval:
dangerous_header: "⚠️ 危險指令: {description}"
choose_long: " [o]僅此一次 | [s]本次工作階段 | [a]永久允許 | [d]拒絕"
choose_short: " [o]僅此一次 | [s]本次工作階段 | [d]拒絕"
prompt_long: " 選擇 [o/s/a/D]: "
prompt_short: " 選擇 [o/s/D]: "
timeout: " ⏱ 逾時 — 已拒絕指令"
allowed_once: " ✓ 本次允許"
allowed_session: " ✓ 本次工作階段內允許"
allowed_always: " ✓ 已加入永久允許清單"
denied: " ✗ 已拒絕"
cancelled: " ✗ 已取消"
blocklist_message: "此指令位於無條件封鎖清單中,無法被批准。"
gateway:
approval_expired: "⚠️ 批准已逾期(代理不再等待)。請讓代理重試。"
draining: "⏳ 正在等待 {count} 個活躍代理結束後重新啟動..."
goal_cleared: "✓ 目標已清除。"
no_active_goal: "目前沒有作用中的目標。"
config_read_failed: "⚠️ 無法讀取 config.yaml{error}"
config_save_failed: "⚠️ 無法儲存設定:{error}"
model:
error_prefix: "錯誤:{error}"
switched: "已切換模型為 `{model}`"
provider_label: "提供方:{provider}"
context_label: "上下文:{tokens} tokens"
max_output_label: "最大輸出:{tokens} tokens"
cost_label: "費用:{cost}"
capabilities_label: "能力:{capabilities}"
prompt_caching_enabled: "提示快取:已啟用"
warning_prefix: "警告:{warning}"
saved_global: "已儲存到 config.yaml`--global`"
session_only_hint: "_僅本次工作階段有效 — 加上 `--global` 可永久儲存_"
current_label: "目前:`{model}`{provider}"
current_tag: "(目前)"
more_models_suffix: "(還有 {count} 個)"
usage_switch_model: "`/model <name>` — 切換模型"
usage_switch_provider: "`/model <name> --provider <slug>` — 切換提供方"
usage_persist: "`/model <name> --global` — 永久儲存"
agents:
header: "🤖 **作用中的代理與任務**"
active_agents: "**作用中代理:** {count}"
this_chat: " · 目前聊天"
more: "... 還有 {count} 個"
running_processes: "**執行中的背景程序:** {count}"
async_jobs: "**閘道非同步任務:** {count}"
none: "沒有作用中的代理或執行中的任務。"
state_starting: "啟動中"
state_running: "執行中"
approve:
no_pending: "沒有待批准的指令。"
once_singular: "✅ 指令已批准。代理正在恢復…"
once_plural: "✅ 指令已批准({count} 條指令)。代理正在恢復…"
session_singular: "✅ 指令已批准(本次工作階段內允許該模式)。代理正在恢復…"
session_plural: "✅ 指令已批准(本次工作階段內允許該模式)({count} 條指令)。代理正在恢復…"
always_singular: "✅ 指令已批准(永久允許該模式)。代理正在恢復…"
always_plural: "✅ 指令已批准(永久允許該模式)({count} 條指令)。代理正在恢復…"
background:
usage: "用法:/background <提示>\n範例/background 摘要今天 HN 上的熱門故事\n\n在獨立工作階段中執行該提示。你可以繼續聊天 — 完成後結果將顯示於此。"
started: "🔄 背景任務已啟動:「{preview}」\n任務 ID{task_id}\n你可以繼續聊天 — 完成後結果將顯示於此。"
branch:
db_unavailable: "工作階段資料庫無法使用。"
no_conversation: "沒有可分支的對話 — 請先傳送一則訊息。"
create_failed: "建立分支失敗:{error}"
switch_failed: "分支已建立,但無法切換到該分支。"
branched_one: "⑂ 已分支至 **{title}**(已複製 {count} 則訊息)\n原始`{parent}`\n分支`{new}`\n使用 `/resume` 切換回原始工作階段。"
branched_many: "⑂ 已分支至 **{title}**(已複製 {count} 則訊息)\n原始`{parent}`\n分支`{new}`\n使用 `/resume` 切換回原始工作階段。"
commands:
usage: "用法:`/commands [page]`"
skill_header: "⚡ **技能指令**"
default_desc: "技能指令"
none: "沒有可用的指令。"
header: "📚 **指令**(共 {total} 個,第 {page}/{total_pages} 頁)"
nav_prev: "`/commands {page}` ← 上一頁"
nav_next: "下一頁 → `/commands {page}`"
out_of_range: "_請求的第 {requested} 頁超出範圍,顯示第 {page} 頁。_"
compress:
not_enough: "對話內容不足,無法壓縮(至少需要 4 則訊息)。"
no_provider: "未設定提供方 — 無法壓縮。"
nothing_to_do: "目前沒有可壓縮的內容(對話記錄仍全部為受保護的上下文)。"
focus_line: "聚焦:\"{topic}\""
summary_failed: "⚠️ 摘要產生失敗({error})。{count} 則歷史訊息已被移除並以佔位符取代;先前的上下文已無法復原。建議檢查 auxiliary.compression 模型設定。"
aux_failed: " 設定的壓縮模型 `{model}` 失敗({error})。已使用主要模型復原 — 上下文完整 — 但您可能想檢查 config.yaml 中的 `auxiliary.compression.model`。"
failed: "壓縮失敗:{error}"
debug:
upload_failed: "✗ 無法上傳除錯報告:{error}"
header: "**除錯報告已上傳:**"
auto_delete: "⏱ 貼上的內容將於 6 小時後自動刪除。"
full_logs_hint: "如需上傳完整紀錄,請在 CLI 中使用 `hermes debug share`。"
share_hint: "請將這些連結分享給 Hermes 團隊以取得支援。"
deny:
stale: "❌ 指令已拒絕(批准已過期)。"
no_pending: "沒有待拒絕的指令。"
denied_singular: "❌ 指令已拒絕。"
denied_plural: "❌ 指令已拒絕({count} 條指令)。"
fast:
not_supported: "⚡ /fast 僅適用於支援 Priority Processing 的 OpenAI 模型。"
status: "⚡ Priority Processing\n\n目前模式`{mode}`\n\n_用法_ `/fast <normal|fast|status>`"
unknown_arg: "⚠️ 未知參數:`{arg}`\n\n**有效選項:** normal、fast、status"
saved: "⚡ ✓ Priority Processing**{label}**(已儲存到設定)\n_下一則訊息生效_"
session_only: "⚡ ✓ Priority Processing**{label}**(僅本次工作階段)"
label_fast: "FAST"
label_normal: "NORMAL"
status_fast: "fast"
status_normal: "normal"
footer:
status: "📎 執行階段頁尾:**{state}**\n欄位`{fields}`\n平台`{platform}`"
usage: "用法:`/footer [on|off|status]`"
saved: "📎 執行階段頁尾:**{state}**{example}\n_已全域儲存 — 下一則訊息生效_"
example_line: "\n範例`{preview}`"
state_on: "ON"
state_off: "OFF"
goal:
unavailable: "此工作階段不支援目標功能。"
no_goal_set: "未設定目標。"
paused: "⏸ 目標已暫停:{goal}"
no_resume: "沒有可恢復的目標。"
resumed: "▶ 目標已恢復:{goal}\n傳送任意訊息繼續或等待 — 我會在下一輪繼續推進。"
invalid: "無效目標:{error}"
set: "⊙ 目標已設定({budget} 輪預算):{goal}\n我會持續工作直到目標完成、你暫停清除目標或預算耗盡。\n控制指令/goal status · /goal pause · /goal resume · /goal clear"
help:
header: "📖 **Hermes 指令**\n"
skill_header: "\n⚡ **技能指令**{count} 個作用中):"
more_use_commands: "\n... 還有 {count} 個。使用 `/commands` 檢視完整分頁清單。"
insights:
invalid_days: "無效的 --days 值:{value}"
error: "產生洞察時發生錯誤:{error}"
kanban:
error_prefix: "⚠ kanban 錯誤:{error}"
subscribed_suffix: "(已訂閱 — 當 {task_id} 完成或被封鎖時將通知您)"
truncated_suffix: "…(已截斷;如需完整輸出請在終端機執行 `hermes kanban …`"
no_output: "(無輸出)"
personality:
none_configured: "`{path}/config.yaml` 中未設定人格"
header: "🎭 **可用人格**\n"
none_option: "• `none` —(不套用人格覆寫)"
item: "• `{name}` — {preview}"
usage: "\n用法`/personality <name>`"
save_failed: "⚠️ 儲存人格變更失敗:{error}"
cleared: "🎭 已清除人格 — 使用基礎代理行為。\n_下一則訊息生效_"
set_to: "🎭 人格已設定為 **{name}**\n_下一則訊息生效_"
unknown: "未知人格:`{name}`\n\n可用{available}"
profile:
header: "👤 **設定檔:** `{profile}`"
home: "📂 **主目錄:** `{home}`"
reasoning:
level_default: "medium預設"
level_disabled: "none已停用"
scope_session: "工作階段覆寫"
scope_global: "全域設定"
status: "🧠 **推理設定**\n\n**強度:** `{level}`\n**範圍:** {scope}\n**顯示:** {display}\n\n_用法_ `/reasoning <none|minimal|low|medium|high|xhigh|reset|show|hide> [--global]`"
display_on: "開啟 ✓"
display_off: "關閉"
display_set_on: "🧠 ✓ 推理顯示:**開啟**\n在 **{platform}** 上每次回應前將顯示模型的思考過程。"
display_set_off: "🧠 ✓ **{platform}** 上的推理顯示:**關閉**"
reset_global_unsupported: "⚠️ 不支援 `/reasoning reset --global`。請使用 `/reasoning <level> --global` 變更全域預設值。"
reset_done: "🧠 ✓ 已清除本工作階段的推理覆寫;回退至全域設定。"
unknown_arg: "⚠️ 未知參數:`{arg}`\n\n**有效級別:** none, minimal, low, medium, high, xhigh\n**顯示:** show, hide\n**持久化:** 加上 `--global` 可跨工作階段儲存"
set_global: "🧠 ✓ 推理強度已設定為 `{effort}`(已儲存到設定)\n_下一則訊息生效_"
set_global_save_failed: "🧠 ✓ 推理強度已設定為 `{effort}`(僅本工作階段 — 設定儲存失敗)\n_下一則訊息生效_"
set_session: "🧠 ✓ 推理強度已設定為 `{effort}`(僅本工作階段 — 加上 `--global` 可持久化)\n_下一則訊息生效_"
reload_mcp:
cancelled: "🟡 已取消 /reload-mcp。MCP 工具未變更。"
always_followup: " 後續 `/reload-mcp` 呼叫將不再要求確認。可在 `config.yaml` 中將 `approvals.mcp_reload_confirm: true` 重新啟用。"
confirm_prompt: "⚠️ **確認 /reload-mcp**\n\n重新載入 MCP 伺服器會為本工作階段重建工具集,並**使提供方提示快取失效** — 下一則訊息將重新傳送完整輸入 token。在長上下文或高推理模型上這可能成本較高。\n\n請選擇\n• **批准一次** — 立即重新載入\n• **永遠批准** — 立即重新載入並永久關閉此提示\n• **取消** — 保持 MCP 工具不變\n\n_文字備援回覆 `/approve`、`/always` 或 `/cancel`。_"
header: "🔄 **MCP 伺服器已重新載入**\n"
reconnected: "♻️ 已重新連線:{names}"
added: " 已新增:{names}"
removed: " 已移除:{names}"
none_connected: "沒有已連線的 MCP 伺服器。"
tools_available: "\n🔧 來自 {servers} 個伺服器的 {tools} 個工具可用"
failed: "❌ MCP 重新載入失敗:{error}"
reload_skills:
header: "🔄 **技能已重新載入**\n"
no_new: "未偵測到新技能。"
total: "\n📚 {count} 個技能可用"
added_header: " **新增技能:**"
removed_header: " **移除技能:**"
item_with_desc: " - {name}{desc}"
item_no_desc: " - {name}"
failed: "❌ 技能重新載入失敗:{error}"
reset:
header_default: "✨ 工作階段已重設!重新開始。"
header_new: "✨ 新工作階段已啟動!"
header_titled: "✨ 新工作階段已啟動:{title}"
title_rejected: "\n⚠ 標題遭拒絕:{error}"
title_error_untitled: "\n⚠ {error} — 工作階段以未命名方式啟動。"
title_empty_untitled: "\n⚠ 清理後標題為空 — 工作階段以未命名方式啟動。"
tip: "\n✦ 提示:{tip}"
restart:
in_progress: "⏳ 閘道重新啟動已在進行中……"
restarting: "♻ 正在重新啟動閘道。如果 60 秒內未收到通知,請在主控台執行 `hermes gateway restart` 重新啟動。"
resume:
db_unavailable: "工作階段資料庫無法使用。"
no_named_sessions: "找不到已命名的工作階段。\n使用 `/title 我的工作階段` 為目前工作階段命名,然後使用 `/resume 我的工作階段` 返回。"
list_header: "📋 **已命名工作階段**\n"
list_item: "• **{title}**{preview_part}"
list_preview_suffix: " — _{preview}_"
list_footer: "\n用法`/resume <工作階段名稱>`"
list_failed: "無法列出工作階段:{error}"
not_found: "找不到符合 '**{name}**' 的工作階段。\n使用不帶參數的 `/resume` 檢視可用的工作階段。"
already_on: "📌 已在工作階段 **{name}** 上。"
switch_failed: "切換工作階段失敗。"
resumed_one: "↻ 已恢復工作階段 **{title}**{count} 則訊息)。對話已還原。"
resumed_many: "↻ 已恢復工作階段 **{title}**{count} 則訊息)。對話已還原。"
resumed_no_count: "↻ 已恢復工作階段 **{title}**。對話已還原。"
retry:
no_previous: "沒有可重試的上一則訊息。"
rollback:
not_enabled: "檢查點未啟用。\n請在 config.yaml 中啟用:\n```\ncheckpoints:\n enabled: true\n```"
none_found: "找不到 {cwd} 的檢查點"
invalid_number: "無效的檢查點編號。請使用 1-{max}。"
restored: "✅ 已還原至檢查點 {hash}{reason}\n已自動儲存回復前的快照。"
restore_failed: "❌ {error}"
set_home:
save_failed: "無法儲存主頻道:{error}"
success: "✅ 主頻道已設定為 **{name}**ID{chat_id})。\n排程任務和跨平台訊息將傳送至此處。"
status:
header: "📊 **Hermes 閘道狀態**"
session_id: "**工作階段 ID** `{session_id}`"
title: "**標題:** {title}"
created: "**建立時間:** {timestamp}"
last_activity: "**最近活動:** {timestamp}"
tokens: "**Token 數:** {tokens}"
agent_running: "**代理執行中:** {state}"
state_yes: "是 ⚡"
state_no: "否"
queued: "**排隊中的後續:** {count}"
platforms: "**已連線平台:** {platforms}"
stop:
stopped_pending: "⚡ 已停止。代理尚未啟動 — 你可以繼續此工作階段。"
stopped: "⚡ 已停止。你可以繼續此工作階段。"
no_active: "沒有可停止的作用中任務。"
title:
db_unavailable: "工作階段資料庫無法使用。"
warn_prefix: "⚠️ {error}"
empty_after_clean: "⚠️ 清理後標題為空。請使用可列印字元。"
set_to: "✏️ 已設定工作階段標題:**{title}**"
not_found: "在資料庫中找不到此工作階段。"
current_with_title: "📌 工作階段:`{session_id}`\n標題**{title}**"
current_no_title: "📌 工作階段:`{session_id}`\n尚未設定標題。用法`/title 我的工作階段名稱`"
topic:
not_telegram_dm: "/topic 指令僅在 Telegram 私人聊天中可用。"
no_session_db: "工作階段資料庫無法使用。"
unauthorized: "您無權在此 bot 上使用 /topic。"
restore_needs_topic: "若要恢復工作階段,請先建立或開啟一個 Telegram topic然後在該 topic 中傳送 /topic <session-id>。若要建立新 topic請開啟 All Messages 並在其中傳送任意訊息。"
topics_disabled: "此 bot 尚未啟用 Telegram topics。\n\n啟用方法\n1. 開啟 @BotFather。\n2. 選擇您的 bot。\n3. 開啟 Bot Settings → Threads Settings。\n4. 開啟 Threaded Mode並確保允許使用者建立新 thread。\n\n然後再次傳送 /topic。"
topics_user_disallowed: "Telegram topics 已啟用,但不允許使用者建立 topics。\n\n開啟 @BotFather → 選擇您的 bot → Bot Settings → Threads Settings然後關閉 'Disallow users to create new threads'。\n\n然後再次傳送 /topic。"
enable_failed: "啟用 Telegram topic 模式失敗:{error}"
bound_status: "此 topic 已連結至:\n工作階段{label}\nID{session_id}\n\n使用 /new 將此 topic 取代為新工作階段。\n如需平行作業請開啟 All Messages 並在其中傳送訊息以建立另一個 topic。"
thread_ready: "Telegram 多工作階段 topics 已啟用。\n\n此 topic 將作為獨立的 Hermes 工作階段使用。使用 /new 取代此 topic 目前的工作階段。如需平行作業,請開啟 All Messages 並在其中傳送訊息以建立另一個 topic。"
untitled_session: "未命名工作階段"
undo:
nothing: "沒有可復原的內容。"
removed: "↩️ 已復原 {count} 則訊息。\n已移除「{preview}」"
update:
platform_not_messaging: "✗ /update 僅在訊息平台上可用。請在終端機執行 `hermes update`。"
not_git_repo: "✗ 不是 git 儲存庫 — 無法更新。"
hermes_cmd_not_found: "✗ 找不到 `hermes` 指令。Hermes 正在執行,但更新指令無法在 PATH 上或透過目前的 Python 解譯器找到執行檔。請嘗試在終端機中手動執行 `hermes update`。"
start_failed: "✗ 啟動更新失敗:{error}"
starting: "⚕ 正在啟動 Hermes 更新…… 進度將在此處顯示。"
usage:
rate_limits: "⏱️ **速率限制:** {state}"
header_session: "📊 **工作階段 token 使用情況**"
label_model: "模型:`{model}`"
label_input_tokens: "輸入 token{count}"
label_cache_read: "快取讀取 token{count}"
label_cache_write: "快取寫入 token{count}"
label_output_tokens: "輸出 token{count}"
label_total: "總計:{count}"
label_api_calls: "API 呼叫次數:{count}"
label_cost: "費用:{prefix}${amount}"
label_cost_included: "費用:已包含"
label_context: "上下文:{used} / {total}{pct}%"
label_compressions: "壓縮次數:{count}"
header_session_info: "📊 **工作階段資訊**"
label_messages: "訊息數:{count}"
label_estimated_context: "預估上下文:~{count} 個 token"
detailed_after_first: "_首次代理回應後可檢視詳細使用情況_"
no_data: "此工作階段沒有可用的使用資料。"
verbose:
not_enabled: "`/verbose` 指令未在訊息平台上啟用。\n\n請在 `config.yaml` 中啟用:\n```yaml\ndisplay:\n tool_progress_command: true\n```"
mode_off: "⚙️ 工具進度:**OFF** — 不顯示任何工具活動。"
mode_new: "⚙️ 工具進度:**NEW** — 工具變更時顯示(預覽長度:`display.tool_preview_length`,預設 40。"
mode_all: "⚙️ 工具進度:**ALL** — 顯示每次工具呼叫(預覽長度:`display.tool_preview_length`,預設 40。"
mode_verbose: "⚙️ 工具進度:**VERBOSE** — 顯示每次工具呼叫及完整參數。"
saved_suffix: "_已為 **{platform}** 儲存 — 下一則訊息生效_"
save_failed: "_無法儲存到設定{error}_"
voice:
enabled_voice_only: "語音模式已啟用。\n當你傳送語音訊息時我會以語音回覆。\n使用 /voice tts 讓所有訊息都收到語音回覆。"
disabled_text: "語音模式已停用。僅文字回覆。"
tts_enabled: "自動 TTS 已啟用。\n所有回覆都將包含一則語音訊息。"
status_mode: "語音模式:{label}"
status_channel: "語音頻道:#{channel}"
status_participants: "參與人數:{count}"
status_member: " - {name}{status}"
speaking: "(正在說話)"
enabled_short: "語音模式已啟用。"
disabled_short: "語音模式已停用。"
label_off: "關閉(僅文字)"
label_voice_only: "開啟(僅對語音訊息進行語音回覆)"
label_all: "TTS對所有訊息進行語音回覆"
yolo:
disabled: "⚠️ 本工作階段 YOLO 模式 **已關閉** — 危險指令將需要批准。"
enabled: "⚡ 本工作階段 YOLO 模式 **已開啟** — 所有指令自動批准。請謹慎使用。"
shared:
session_db_unavailable: "工作階段資料庫無法使用。"
session_db_unavailable_prefix: "工作階段資料庫無法使用"
session_not_found: "資料庫中找不到此工作階段。"
warn_passthrough: "⚠️ {error}"