在 Hexo 中,如果你想让博客支持多种语言(例如同时提供中文和英文版本),就需要使用国际化(Internationalization,简称 i18n)功能。这里的 “i18n” 是单词 internationalization 的缩写,因为首字母 i 和尾字母 n 之间有 18 个字母,所以用 i18n 代表。
这就好比开了一家餐厅,你准备了中文菜单和英文菜单。当中国客人进来时,你递上中文菜单;当外国客人进来时,你递上英文菜单。Hexo 的 i18n 功能就是帮你自动判断该给读者展示哪种语言的“菜单”。
下面我们将详细讲解如何配置多语言环境、编写语言文件以及在模板中调用翻译内容。
一、基础配置:设定默认语言
首先,你需要告诉 Hexo 你的博客默认使用什么语言,或者支持哪些语言以及它们的优先级。这需要修改站点根目录下的 _config.yml 配置文件。
1. 单语言配置
如果你只需要一种语言,直接设置 language 为对应的语言代码即可。
配置示例:
1 | # _config.yml |
这里 zh-tw 代表繁体中文。其他常见代码包括 zh-cn (简体中文), en (英语), ja (日语) 等。
2. 多语言配置(语言回退机制)
如果你希望博客支持多种语言,并且设定一个 fallback(回退)顺序,可以将 language 设置为一个列表。Hexo 会按照列表顺序依次查找翻译,如果第一种语言找不到对应的翻译字符串,就会尝试第二种,以此类推。
配置示例:
1 | # _config.yml |
解读:
- 首选语言是
zh-tw(繁体中文)。 - 如果在繁体中文的语言文件中找不到某个词条的翻译,Hexo 会自动去
en(英语)的语言文件中查找。 - 这种机制确保了即使某种语言的翻译不完整,网站也不会显示缺失的代码键名,而是显示备用语言的内容。
二、语言文件:存储翻译内容
语言文件是存储所有翻译文本的地方。Hexo 支持使用 YAML 或 JSON 格式编写这些文件。
1. 文件位置与命名
语言文件必须放在主题文件夹下的 languages 目录中。
文件名必须与你在 _config.yml 中设置的语言代码一致。
目录结构示例:
1 | themes/your-theme/ |
2. 文件内容与格式
在语言文件中,你可以使用层级结构来组织翻译键(Key)。Hexo 还支持 printf 格式的占位符,用于处理动态内容(如数字)。
配置示例 (en.yml):
1 | index: |
关键点解析:
- 层级结构:
index.title对应 YAML 中的缩进层级。在代码中调用时,使用点号.连接,即'index.title'。 - 复数处理 (Pluralization):这是 i18n 中非常重要的概念。不同语言对数量的表达不同(例如英语中 1 个视频是 “One video”,2 个视频是 “Two videos”,0 个视频是 “No videos”)。
zero: 当数量为 0 时使用的文本。one: 当数量为 1 时使用的文本。other: 当数量为其他数值(2, 3, 100…)时使用的文本。%d: 这是一个占位符,代表具体的数字。Hexo 在渲染时会自动将%d替换为实际传入的数字。
三、模板开发:获取翻译字符串
在主题的模板文件(如 .ejs, .swig, .pug)中,你不能直接写死文字(如 “Home”),而应该使用 Hexo 提供的辅助函数(Helpers)来获取翻译后的字符串。这样当你切换语言时,页面上的文字会自动变化。
Hexo 提供了两个核心辅助函数:__() 和 _p()。
1. __() 函数:普通文本翻译
功能:用于获取普通的、不涉及数量变化的翻译字符串。
语法:
1 | <%= __('key_name') %> |
key_name:语言文件中定义的键名,支持点号层级,如'index.title'。
示例:
假设语言文件中有 index.title: Home。
1 | <%= __('index.title') %> |
2. _p() 函数:复数文本翻译
功能:专门用于处理根据数量变化而改变形式的字符串(复数形式)。
语法:
1 | <%= _p('key_name', count) %> |
key_name:语言文件中定义了zero,one,other层级的键名。count:具体的数字。Hexo 会根据这个数字自动选择zero,one或other对应的文本,并将%d替换为该数字。
示例:
假设语言文件定义如下:
1 | video: |
场景 A:数量为 0
1 | <%= _p('index.video', 0) %> |
场景 B:数量为 1
1 | <%= _p('index.video', 1) %> |
场景 C:数量为 3
1 | <%= _p('index.video', 3) %> |
概念辨析:__ vs _p
__():像是一个简单的查字典工具。你给它一个词,它返回对应的翻译。适用于标题、按钮文字、固定描述等。_p():像是一个智能的语法转换器。它不仅查字典,还会根据你给的数量,自动调整名词的单复数形式。适用于“x 条评论”、“x 篇文章”、“x 小时前”等涉及数量的场景。如果不使用_p()而强行用__()拼接字符串(例如count + ' videos'),在中文里可能没问题,但在俄语、阿拉伯语等复数规则复杂的语言中会显得非常不专业。
四、路径与语言侦测:如何识别用户语言
Hexo 需要知道当前页面应该使用哪种语言来渲染。它提供了两种主要方式来确定语言:通过 Front-matter 手动指定,或通过 URL 路径自动侦测。
1. 在 Front-matter 中指定
你可以在每篇文章或页面的头部(Front-matter)中,显式地声明该页面使用的语言。
示例 (文章头部):
1 |
|
或者使用 language 字段:
1 |
|
这种方式优先级最高,适合那些明确属于特定语言的文章。
2. 自动侦测 (i18n_dir 配置)
更常见的做法是让 Hexo 根据 URL 路径自动判断语言。这需要在站点配置文件 _config.yml 中设置 i18n_dir。
配置说明:
1 | # _config.yml |
:lang是一个变量,表示 Hexo 会提取 URL 中的第一段路径作为语言代码。
工作原理与示例:
当设置了 i18n_dir: :lang 后,Hexo 会解析访问的 URL 路径:
访问
/index.html- 路径中没有语言代码。
- Hexo 使用
_config.yml中配置的默认语言(即language列表中的第一个,如zh-tw)。 - 结果:以繁体中文渲染。
访问
/en/index.html- Hexo 检测到第一段路径
en。 - Hexo 检查
en是否是有效的语言代码(即是否存在对应的en.yml文件或在language列表中)。 - 如果是,则以英语渲染。
- 结果:以英文渲染。
- Hexo 检测到第一段路径
访问
/zh-tw/archives/index.html- Hexo 检测到第一段路径
zh-tw。 - 确认为有效语言。
- 结果:以繁体中文渲染归档页。
- Hexo 检测到第一段路径
重要注意事项:有效性验证
Hexo 不会盲目地将 URL 的第一段当作语言。它有一个验证机制:捕获到的字符串唯有在语言文件存在的情况下,才会被当作是语言。
案例分析:
假设你的 languages 文件夹里只有 en.yml 和 zh-tw.yml。
访问
/archives/index.html- Hexo 尝试解析第一段
archives。 - 检查是否存在
archives.yml或者archives是否在语言列表中? - 不存在。
- 结论:
archives不被当成是语言。Hexo 会忽略它,继续使用默认语言渲染该页面。这保证了正常的目录结构(如/archives/,/categories/,/tags/)不会被误判为语言切换。
- Hexo 尝试解析第一段
访问
/en/archives/index.html- Hexo 解析第一段
en。 - 检查是否存在
en.yml? - 存在。
- 结论:
en被识别为语言。页面将以英语渲染,路径中的archives被视为正常的页面路径。
- Hexo 解析第一段
总结
实现 Hexo 国际化的核心流程如下:
- 配置:在
_config.yml设置language列表和i18n_dir: :lang。 - 翻译:在主题
languages目录下创建对应的.yml文件,定义好普通文本和复数文本(zero/one/other)。 - 调用:在模板中使用
<%= __('key') %>获取普通文本,使用<%= _p('key', count) %>获取复数文本。 - 访问:用户通过访问
/en/xxx或/zh-tw/xxx来切换语言,Hexo 会自动验证路径并加载对应的语言包。
通过这套机制,你可以轻松构建一个面向全球读者的多语言博客,而无需为每种语言复制一套模板文件。