Hermes 语言包指南:让 CLI、网关和桌面端说你的语言


你的团队里有一半人读中文界面,另一半人读英文,于是每天都有那么几句提示被误读。有一次终端里弹出的危险操作确认是一长串英文,同事匆匆扫了一眼就按了回车;另一个人想把界面切成自己的母语,输入 hermes config set display.language pl,得到的是 ✗ Unknown language 'pl'。Hermes 内置 17 种界面语言,但波兰语、韩语、巴西葡萄牙语都不在名单里,光靠改配置变不出来。语言包(language pack)解决的就是这件事:一个只装 YAML 文件的插件,能把 CLI 的批准提示、消息网关的回复、工具动词、提示语,以及 hermes --tui 和桌面端的界面文字一起换掉,而且全程不需要写一行 Python。

17 种内置语言,名单却是可插拔的

内置的一共 17 种,用哪一种由 display.language 决定。内置目录放在 locales/ 下:af、ar、de、en、es、fr、ga、hu、it、ja、ko、pt、ru、tr、uk、zh-hant、zh。

hermes config set display.language 接受任何一层能提供该语言的 id。如果这个 id 谁也不认识,命令会被直接拒绝,并把当前可用的语言列出来:

$ hermes config set display.language pl
✗ Unknown language 'pl' for display.language. Available: en, af, ar, de, es, ...
  Install a language pack plugin (hermes plugins install <pack>) or drop <HERMES_HOME>/locales/<id>.yaml to add one.

这条报错本身就把两条出路写在里面了:装一个语言包插件,或者自己放一个覆盖文件。另外别忘了 .env 里的 HERMES_LANGUAGE 仍然会盖过 display.language——排查“我明明改了配置为什么没生效”时,这是最常被忽略的一处。

这套机制来自 v0.22.0 的工作:PR #126296 把 CLI、消息网关、TUI 和桌面端里所有面向用户的字符串都接到了同一份翻译目录上,语言包才有地方挂钩,细节可以看 v0.22.0 发布说明。

装一个语言包

语言包走的是普通插件的安装流程,还没装 Hermes 的话先看安装指南。装包和切语言一共两条命令:

hermes plugins install hermes-lang-pt-br   # 给插件目录里的名字,或者直接给仓库地址
hermes config set display.language pt-br

2026 年 10 月 14 日合并进官方插件目录的两个真实语言包是韩语的 hermes-lang-ko 和巴西葡萄牙语的 hermes-lang-pt-br;官方文档里示范的则是一个波兰语包(https://github.com/teknium1/hermes-lang-pl)。

装完记得重启正在跑的网关或 TUI,让它们重新加载。TUI 和桌面端的语言切换菜单会把内置语言、你自己的覆盖文件、以及每一个已安装的语言包列在一起,显示的是这门语言的自称名(endonym,比如 Polski)而不是代码。语言包怎么被安装、怎么被发现,和普通插件是同一套流程,可以参考插件目录指南。

字符串是从哪来的

Hermes 查一个字符串时会从上到下走过这几层,取第一个命中的结果:

  1. 声明了 provides_locales 的插件语言包(两个包覆盖同一个 key 时,后加载的那个生效)
  2. 你自己的覆盖文件 <HERMES_HOME>/locales/<lang>.yaml,按 profile 分开,命名 profile 是 ~/.hermes/profiles/<name>/locales/
  3. Hermes 自带的 locales/<lang>.yaml

这三层都查不到,就用同样的顺序再查一遍英文的三层,最后才把原始 key 直接显示出来。每一层都可以是部分的——语言包只写它想改的那些 key 就行,不用整份复制。

自己写一个包,不需要 Python

一个语言包就是一坨 YAML,目录结构如下:

hermes-lang-pl/
  plugin.yaml
  locales/
    pl.yaml            # 核心:approval.*、gateway.*、cli.*、display.*、slash.*、tips.* 等
    pl.tui.yaml        # 可选:hermes --tui 的界面文字
    pl.desktop.yaml    # 可选:桌面端

plugin.yaml 里声明这个包提供哪种语言:

name: hermes-lang-pl
version: 1.0.0
description: Polish language pack for Hermes
provides_locales:
  - id: pl            # 小写 BCP-47 风格标签:pl、pt-br、zh-hant
    endonym: Polski   # 显示在语言切换菜单里的自称名
    rtl: false        # 从右到左的文字写 true,桌面端布局会跟着镜像

provides_locales 也可以只写 id(- pl),这时 endonym 默认就是 id。只要 manifest 里有这一项,插件加载器就会自动注册目录里的 locales/<lang>[.tui|.desktop].yaml,不用额外代码。

本身已经有 Python 代码的插件,可以自己注册语言文件:ctx.register_locale("pl", path_or_mapping, endonym="Polski", rtl=False, surface="core"),surface 可选 core、tui 或 desktop;也可以直接用 ctx.register_locale_dir(dir) 一次注册整目录。注册会在插件卸载时撤销,而且它从来不改变 display.language。

校验和占位符

写完先跑一遍校验器:

hermes plugins validate ./hermes-lang-pl

它会检查每个声明的 id 都有对应的 locales/<id>.yaml,每个文件能正常解析,而且值全部是文本——数字、列表、true/false、空值都会被当成错误。它还会把英文目录里不存在的 key 逐个列出来警告你:这些 key 不会报错,只是永远不生效。写的时候也别拿 YAML 的保留字当 key,包括 on、off、yes、no。

占位符是第二个容易踩的坑。核心(Python 侧)字符串用的是具名占位符,英文写的是 {count},翻译里就必须原样保留 {count}——少一个或者拼错,这个 key 会整个回退成英文。TUI 和桌面端里那些英文原值带参数的条目,用的是位置占位符 {0}、{1}。

不装插件也能改两句

只想改一两句话,不用做插件。往 Hermes home 里放一个部分覆盖文件就行:

# ~/.hermes/locales/en.yaml —— 只写你想改的 key
approval:
  denied: "      ✗ Nope."

这个覆盖只对当前 profile 生效,有名字的 profile 用 ~/.hermes/profiles/<name>/locales/。给 Hermes 没有内置的语言写覆盖文件,也会让这门语言变得可以选。文件在下次启动或者下次切换 display.language 时被读取。

语言包不翻译什么

语言包负责的只是静态界面文字:CLI 的批准提示、网关回复、工具动词、提示语、TUI 界面和桌面端。Agent 的回答、工具输出、日志,以及斜杠命令的名字都不在其中。想让 Agent 本身用另一种语言回答,直接在提示里说清楚就行——这是两件不同的事。

出问题时先看这三条

  • 报 Unknown language ... for display.language:包没装上或没启用(用 hermes plugins list 看一眼),或者 provides_locales 里的 id 和文件名对不上——id 是 pl,文件就得叫 locales/pl.yaml。
  • 某句话还是英文:这个 key 不在英文目录里(hermes plugins validate 会把它们列出来),或者占位符集合和英文不一致。
  • 语言在列表里,但 TUI 或桌面端还是英文:包里没有 .tui.yaml / .desktop.yaml,这两个界面只显示英文加上语言包提供的那部分。

更多 Hermes 的配置与用法可以翻博客列表。