多语言

2026-06-20

内容多语言

内容按语言代码分目录存放。启动预览时,通过 --lang 参数指定语言:

# 通过参数指定
everkm-publish serve --lang zh_CN

# 或者通过环境变量指定
export EVERKM_LANG=zh_CN
everkm-publish serve

例如,支持 zh_CN, en_US 两种语言, 目录结构如下:

<work_dir>/
├── zh_CN/
│   └── blog/
│       └── hello.md
├── en_US/
│   └── blog/
│       └── hello.md
└── __everkm/
    └── everkm.yaml

未指定 --lang 时,内容根为 <work_dir>/(单语言站兼容)。

预览时切换语言

本地预览时,无需重启服务即可切换界面语言:

  • URL 参数:http://localhost:9081/?_lang=zh_CN
  • Cookie:设置 __lang=zh_CN

适用于查看站点配置、面包屑、模板等随语言变化的文案,正文内容仅支持通过命令行参数切换。

配置文案多语言

站点配置(everkm.yaml)中的字符串值,可使用 @i18n:<key> 引用语言包中的译文:

config:
  site:
    name: "@i18n:site.title"

folders:
  "/docs/":
    breadcrumbs:
      - title: "@i18n:nav.docs"
        url: /docs/

渲染时按当前 --lang / ?_lang / cookie 自动替换为对应语言文本。

注意@i18n: 仅支持整段替换,不支持内嵌混合(如 欢迎 @i18n:site.name)。

语言包位置与优先级

语言包支持 *.i18n.md*.i18n.yaml 两种格式。合并顺序(低 → 高,后者覆盖前者):

  1. 主题 templates/ 目录及其子目录
  2. __everkm/extend/templates/(若存在)
  3. __everkm/extend/dcard/(若存在;*.i18n.yaml 文件名自动作为命名空间,如 download.i18n.yaml 中 key 为 download.*
  4. __everkm/extend/i18n/(项目级,优先级最高)

预览时修改 extend/i18n/ 下的语言包自动生效,无需重启。extend/ 变更会触发模板与语言包重载。

项目语言包(*.i18n.yaml

项目语言包存放在 __everkm/extend/i18n/,采用单文件多语言格式(一个文件包含所有语言的译文)。

文件命名

文件名说明
_root.i18n.yaml根命名空间,key 无前缀
{name}.i18n.yaml命名空间为 {name},key 自动加 name. 前缀

文件名仅允许 [A-Za-z0-9_]+_root 是根命名空间专用名称。

翻译对象写法

多语言条目须为 mapping,且必须_default(fallback 译文)。同级其它非 _ 开头的 string 子项为语言码。

# __everkm/extend/i18n/_root.i18n.yaml

site:
  title:
    _default: Everkm Publish
    zh_CN: 易记发布
    en_US: Everkm Publish
    _memo: 浏览器标题、og:title    # 备注,不参与渲染

nav:
  home:
    _default: Home
    zh_CN: 首页
    en_US: Home

# 纯字符串 leaf(单语,等价 { _default: "..." })
blog: Blog

规则

  • _default(必填) — 标记翻译对象,并提供 fallback 译文
  • _memo — 备注字段,忽略不渲染
  • _ 开头的 string 子项 — 语言码译文
  • 纯字符串 leaf — 等价 { _default: "<text>" },仅写入 _default
  • _default 的 mapping — 分组节点,继续下钻;同层 string 子项视为嵌套 key,不是语言码
  • 翻译对象内不得嵌套 mapping,否则报错并忽略该项

语言码约定

语言码与站点 --lang 参数字面一致,不做 zhzh_CN 自动转换:

--lang 参数yaml 中写法
zh_CNzh_CN:
en_USen_US:
zhzh:

命名空间语言包

# __everkm/extend/i18n/shop.i18n.yaml(namespace="shop")

cart:
  title:
    _default: Cart
    zh_CN: 购物车
    en_US: Cart
checkout: Pay now      # → shop.checkout @ _default

模板中引用时带命名空间前缀:@i18n:shop.cart.title

Lookup 优先级

对 key K、请求语言 L(如 zh_CN):

  1. L 语言的译文(精确匹配)
  2. config.default_lang 语言的译文
  3. _default 语言槽的译文
  4. 保持原样 @i18n:<key>(日志 warn)

与主题 *.i18n.md 共存

主题仍用现有 templates/*.i18n.md(按语言分文件)。合并时项目 yaml 覆盖主题 md 的同 key 译文。

模板 UI 文案

主题模板内的界面文案通过内置函数 t 读取语言包。

主题语言包格式

在主题 templates/ 或其子目录下放置语言包,支持两种格式,可共存。

.i18n.md(按语言分文件)

一级标题作为 key,所辖区域皆为对应内容,两端空白自动忽略。

文件命名<Language Code>.i18n.md;命名空间:<Namespace>.<Language Code>.i18n.md

en_US.i18n.md

# My name
Everkm Publish

details.en_US.i18n.md

# toc
Table Of Contents

.i18n.yaml(单文件多语言)

文件命名{Namespace}.i18n.yaml,文件名即命名空间。

# templates/nav.i18n.yaml(namespace="nav")
home:
  _default: Home
  zh_CN: 首页
  en_US: Home

同 key 时 .i18n.yaml 覆盖 .i18n.md;项目级 extend/i18n/*.i18n.yaml 优先级最高(见上文合并顺序)。

模板中引用

带有命名空间的 key 需加前缀 <namespace>: (注意后面有一个空格):

<p>{{t(text="My name")}}</p>
<p>{{t(text="details: toc")}}</p>
<p>{{t(text="nav: home")}}</p>

多语言图片

  1. 在同目录放置同名图片,扩展名前加 .<Language Code>,如 logo.en_US.png
  2. 模板中用 img_src
<img src="{{img_src(file='logo.png')}}" />

--lang=en_US 时输出 logo.en_US.png