hexo 学习 0030:hexo 国际化(i18n)

在 Hexo 中,如果你想让博客支持多种语言(例如同时提供中文和英文版本),就需要使用国际化(Internationalization,简称 i18n)功能。这里的 “i18n” 是单词 internationalization 的缩写,因为首字母 i 和尾字母 n 之间有 18 个字母,所以用 i18n 代表。

这就好比开了一家餐厅,你准备了中文菜单和英文菜单。当中国客人进来时,你递上中文菜单;当外国客人进来时,你递上英文菜单。Hexo 的 i18n 功能就是帮你自动判断该给读者展示哪种语言的“菜单”。

下面我们将详细讲解如何配置多语言环境、编写语言文件以及在模板中调用翻译内容。

一、基础配置:设定默认语言

首先,你需要告诉 Hexo 你的博客默认使用什么语言,或者支持哪些语言以及它们的优先级。这需要修改站点根目录下的 _config.yml 配置文件。

1. 单语言配置

如果你只需要一种语言,直接设置 language 为对应的语言代码即可。

配置示例:

1
2
# _config.yml
language: zh-tw

这里 zh-tw 代表繁体中文。其他常见代码包括 zh-cn (简体中文), en (英语), ja (日语) 等。

2. 多语言配置(语言回退机制)

如果你希望博客支持多种语言,并且设定一个 fallback(回退)顺序,可以将 language 设置为一个列表。Hexo 会按照列表顺序依次查找翻译,如果第一种语言找不到对应的翻译字符串,就会尝试第二种,以此类推。

配置示例:

1
2
3
4
# _config.yml
language:
- zh-tw
- en

解读:

  • 首选语言是 zh-tw(繁体中文)。
  • 如果在繁体中文的语言文件中找不到某个词条的翻译,Hexo 会自动去 en(英语)的语言文件中查找。
  • 这种机制确保了即使某种语言的翻译不完整,网站也不会显示缺失的代码键名,而是显示备用语言的内容。

二、语言文件:存储翻译内容

语言文件是存储所有翻译文本的地方。Hexo 支持使用 YAMLJSON 格式编写这些文件。

1. 文件位置与命名

语言文件必须放在主题文件夹下的 languages 目录中。
文件名必须与你在 _config.yml 中设置的语言代码一致。

目录结构示例:

1
2
3
4
5
6
themes/your-theme/
├── languages/
│ ├── zh-tw.yml # 繁体中文翻译
│ ├── zh-cn.yml # 简体中文翻译
│ └── en.yml # 英文翻译
└── ...

2. 文件内容与格式

在语言文件中,你可以使用层级结构来组织翻译键(Key)。Hexo 还支持 printf 格式的占位符,用于处理动态内容(如数字)。

配置示例 (en.yml):

1
2
3
4
5
6
7
index:
title: Home
add: Add
video:
zero: No videos
one: One video
other: "%d videos"

关键点解析:

  • 层级结构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
2
3
<%= __('index.title') %>
// 如果当前语言是 en,输出: Home
// 如果当前语言是 zh-tw 且对应翻译为 '首頁',输出: 首頁

2. _p() 函数:复数文本翻译

功能:专门用于处理根据数量变化而改变形式的字符串(复数形式)。
语法

1
<%= _p('key_name', count) %>
  • key_name:语言文件中定义了 zero, one, other 层级的键名。
  • count:具体的数字。Hexo 会根据这个数字自动选择 zero, oneother 对应的文本,并将 %d 替换为该数字。

示例
假设语言文件定义如下:

1
2
3
4
video:
zero: No videos
one: One video
other: "%d videos"

场景 A:数量为 0

1
2
<%= _p('index.video', 0) %>
// 输出: No videos

场景 B:数量为 1

1
2
<%= _p('index.video', 1) %>
// 输出: One video

场景 C:数量为 3

1
2
3
<%= _p('index.video', 3) %>
// 输出: 3 videos
// 注意:%d 被替换成了 3

概念辨析:__ vs _p

  • __():像是一个简单的查字典工具。你给它一个词,它返回对应的翻译。适用于标题、按钮文字、固定描述等。
  • _p():像是一个智能的语法转换器。它不仅查字典,还会根据你给的数量,自动调整名词的单复数形式。适用于“x 条评论”、“x 篇文章”、“x 小时前”等涉及数量的场景。如果不使用 _p() 而强行用 __() 拼接字符串(例如 count + ' videos'),在中文里可能没问题,但在俄语、阿拉伯语等复数规则复杂的语言中会显得非常不专业。

四、路径与语言侦测:如何识别用户语言

Hexo 需要知道当前页面应该使用哪种语言来渲染。它提供了两种主要方式来确定语言:通过 Front-matter 手动指定,或通过 URL 路径自动侦测。

1. 在 Front-matter 中指定

你可以在每篇文章或页面的头部(Front-matter)中,显式地声明该页面使用的语言。

示例 (文章头部):

1
2
3
4
5
---
title: Hello World
date: 2026-03-10
lang: zh-tw
---

或者使用 language 字段:

1
2
3
4
---
title: Hello World
language: en
---

这种方式优先级最高,适合那些明确属于特定语言的文章。

2. 自动侦测 (i18n_dir 配置)

更常见的做法是让 Hexo 根据 URL 路径自动判断语言。这需要在站点配置文件 _config.yml 中设置 i18n_dir

配置说明:

1
2
# _config.yml
i18n_dir: :lang
  • :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 列表中)。
    • 如果是,则以英语渲染。
    • 结果:以英文渲染。
  • 访问 /zh-tw/archives/index.html

    • Hexo 检测到第一段路径 zh-tw
    • 确认为有效语言。
    • 结果:以繁体中文渲染归档页。

重要注意事项:有效性验证
Hexo 不会盲目地将 URL 的第一段当作语言。它有一个验证机制:捕获到的字符串唯有在语言文件存在的情况下,才会被当作是语言。

案例分析:
假设你的 languages 文件夹里只有 en.ymlzh-tw.yml

  • 访问 /archives/index.html

    • Hexo 尝试解析第一段 archives
    • 检查是否存在 archives.yml 或者 archives 是否在语言列表中?
    • 不存在
    • 结论:archives 不被当成是语言。Hexo 会忽略它,继续使用默认语言渲染该页面。这保证了正常的目录结构(如 /archives/, /categories/, /tags/)不会被误判为语言切换。
  • 访问 /en/archives/index.html

    • Hexo 解析第一段 en
    • 检查是否存在 en.yml
    • 存在
    • 结论:en 被识别为语言。页面将以英语渲染,路径中的 archives 被视为正常的页面路径。

总结

实现 Hexo 国际化的核心流程如下:

  1. 配置:在 _config.yml 设置 language 列表和 i18n_dir: :lang
  2. 翻译:在主题 languages 目录下创建对应的 .yml 文件,定义好普通文本和复数文本(zero/one/other)。
  3. 调用:在模板中使用 <%= __('key') %> 获取普通文本,使用 <%= _p('key', count) %> 获取复数文本。
  4. 访问:用户通过访问 /en/xxx/zh-tw/xxx 来切换语言,Hexo 会自动验证路径并加载对应的语言包。

通过这套机制,你可以轻松构建一个面向全球读者的多语言博客,而无需为每种语言复制一套模板文件。