多语言网站结构设计与组织方式

config 中定义多种语言并为每篇内容提供翻译,可以同时服务不同地区的用户。利用 i18n 文件管理界面文本,结合语言前缀或子目录结构,确保各语言版本既独立又保持一致性。还可以为不同语言指定各自的 baseURL 与日期格式,使站点更贴近当地习惯。

Hugo 对多语言网站提供了一流的内置支持。下面我们将详细探讨如何配置和组织一个多语言 Hugo 网站。

配置文件设置

第一步是在站点配置文件中定义你希望支持的语言。通常,这在 config.tomlconfig/_default/languages.toml 中完成。

# config.toml

# 默认语言
defaultContentLanguage = "zh"

[languages]
  [languages.zh]
    languageName = "简体中文"
    contentDir = "content/zh"
    weight = 1
    [languages.zh.params]
      languageCode = "zh-cn"

  [languages.en]
    languageName = "English"
    contentDir = "content/en"
    weight = 2
    [languages.en.params]
      languageCode = "en-us"

关键配置项解释

  • defaultContentLanguage: 设定网站的默认语言。当用户访问网站根 URL 时,将显示该语言的内容。
  • [languages]: 一个顶级键,用于存放所有语言的配置。
  • [languages.zh][languages.en]: 每个方括号代表一种语言,zhen 是语言的唯一标识符。
  • languageName: 显示在语言切换器中的语言名称。
  • contentDir: 非常重要,指定该语言的内容文件所在的目录。这是管理多语言内容的最清晰方式。
  • weight: 用于排序,决定语言在语言切换器中的显示顺序。
  • languageCode: (可选)在 params 中设置,用于生成 HTML 的 lang 属性,对 SEO 和浏览器行为有帮助。

内容文件组织

配置好语言后,你需要相应地组织你的内容文件。最推荐、最不易混淆的方式是按目录分离,这也是我们在上面配置中 contentDir 所指定的。

.
└── content/
    ├── en/
    │   ├── about.md
    │   └── blog/
    │       ├── post-1.md
    │       └── post-2.md
    └── zh/
        ├── about.md
        └── blog/
            ├── post-1.md
            └── post-2.md
  • 结构清晰:每个语言的内容完全独立,存放在各自的目录中(content/encontent/zh)。
  • URL 结构:Hugo 会自动为非默认语言的 URL 添加语言前缀。
    • 默认语言(zh):yoursite.com/blog/post-1/
    • 英文(en):yoursite.com/en/blog/post-1/

链接翻译内容

为了让 Hugo 知道 content/en/blog/post-1.mdcontent/zh/blog/post-1.md 的翻译版本,你需要将它们关联起来。Hugo 通过相同的文件路径和文件名来自动完成这个关联。

只要两个不同语言目录下的文件相对路径和文件名一致,Hugo 就会视它们为互译版本。

你也可以在 Front Matter 中使用 translationKey 进行手动关联,但这在目录结构清晰时通常不是必需的。

# content/zh/blog/a-good-day.md
---
title: "美好的一天"
translationKey: "a-good-day-post"
---
# content/en/blog/a-good-day.md
---
title: "A Good Day"
translationKey: "a-good-day-post"
---

4. 翻译界面字符串 (i18n)

网站中除了文章内容,还有很多界面文本,如“上一篇”、“下一篇”、“发布于”等。这些字符串需要通过 Hugo 的 i18n 系统进行翻译。

  1. 创建 i18n 目录:在项目根目录下创建 i18n 文件夹。

  2. 创建语言文件:在 i18n 目录下创建与你的语言代码对应的 TOML, YAML 或 JSON 文件。

    • i18n/zh.toml:

      [read_more]
      other = "阅读更多"
      
    • i18n/en.toml:

      [read_more]
      other = "Read More"
      
  3. 在模板中调用:在你的布局模板(如 layouts/_default/single.html)中使用 i18n 函数。

    <a href="{{ .Permalink }}">{{ i18n "read_more" }}</a>
    

    Hugo 会根据当前页面的语言,自动从对应的 i18n 文件中查找并显示正确的翻译。

在模板中处理多语言

Hugo 提供了一系列强大的模板变量和函数来处理多语言逻辑。

构建语言切换器

你可以通过遍历 .Site.Languages 并检查 .IsTranslated 来创建一个语言切换器。

{{ if .IsTranslated }}
<nav class="lang-switch">
  Languages:
  <ul>
    {{ range .AllTranslations }}
    <li>
      <a href="{{ .Permalink }}">{{ .Language.LanguageName }}</a>
    </li>
    {{ end }}
  </ul>
</nav>
{{ end }}
  • .IsTranslated: 如果当前页面有至少一个翻译版本,则为 true
  • .AllTranslations: 返回一个包含当前页面所有翻译版本(包括它自己)的页面集合。
  • .Permalink: 每个翻译页面的永久链接。
  • .Language.LanguageName: 该翻译页面的语言名称(在 config.toml 中定义)。

获取当前语言信息

  • .Site.Language: 获取当前语言的配置对象。
  • .Site.Language.Lang: 获取当前语言的代码(如 zh)。
  • .Site.LanguagePrefix: 获取当前语言的 URL 前缀(如 /en)。

最佳实践

  • 使用 contentDir:为每种语言设置独立的 contentDir 是最清晰、最推荐的内容组织方式。
  • 保持文件结构同步:尽量保持不同语言内容目录下文件结构的对等性,这有助于 Hugo 自动关联翻译。
  • 利用 i18n 管理所有界面文本:不要在模板中硬编码任何界面文本,全部使用 i18n 函数进行管理。
  • 为图片等多媒体资源考虑本地化:如果图片中包含文字,你可能需要为不同语言提供不同的图片版本。

通过以上步骤,你就可以构建一个功能完善、易于维护的 Hugo 多语言网站。