多语言支持

Hugo 的多语言支持允许您为每个语言和地区提供本地化的内容、图片、日期、货币、数字、百分比和排序规则。Hugo 的多语言框架支持单主机多主机配置。

基础配置

核心设置

在站点根配置文件中配置多语言基础设置:

# hugo.toml
defaultContentLanguage = 'zh'
defaultContentLanguageInSubdir = false
enableMissingTranslationPlaceholders = false
languageCode = 'zh-CN'

[languages]
  [languages.zh]
    baseURL = 'https://example.com'
    languageName = '中文'
    title = '我的网站'
    weight = 1
    
  [languages.en]
    baseURL = 'https://en.example.com'
    languageName = 'English'
    title = 'My Website'
    weight = 2

配置选项详解

defaultContentLanguage

定义默认内容语言的代码:

defaultContentLanguage = 'zh'

defaultContentLanguageInSubdir

控制默认语言是否使用子目录:

# false: https://example.com/
# true:  https://example.com/zh/
defaultContentLanguageInSubdir = false

enableMissingTranslationPlaceholders

在开发时显示缺失翻译的占位符:

# 开发环境建议启用,生产环境关闭
enableMissingTranslationPlaceholders = true

languageCode

站点的语言标签,遵循 RFC 5646 规范:

languageCode = 'zh-CN'  # 中文(中国大陆)
# languageCode = 'zh-TW'  # 中文(台湾)
# languageCode = 'en-US'  # 英语(美国)

语言特定配置

基本语言配置

[languages]
  [languages.zh]
    languageName = '中文'
    languageDirection = 'ltr'
    title = '我的中文网站'
    weight = 1
    disabled = false
    
    # 自定义参数
    [languages.zh.params]
      description = '这是中文网站的描述'
      author = '作者姓名'
      
    # 菜单配置
    [[languages.zh.menu.main]]
      name = '首页'
      url = '/'
      weight = 10
      
    [[languages.zh.menu.main]]
      name = '关于'
      url = '/about/'
      weight = 20
      
  [languages.en]
    languageName = 'English'
    languageDirection = 'ltr'
    title = 'My English Website'
    weight = 2
    
    [languages.en.params]
      description = 'This is the description of my English website'
      author = 'Author Name'
      
    [[languages.en.menu.main]]
      name = 'Home'
      url = '/'
      weight = 10
      
    [[languages.en.menu.main]]
      name = 'About'
      url = '/about/'
      weight = 20

高级配置选项

时区配置

[languages.zh]
  timeZone = 'Asia/Shanghai'
  
[languages.en]
  timeZone = 'America/New_York'

分页配置

[languages.zh]
  paginatePath = '页面'  # /blog/页面/2/
  
[languages.en]
  paginatePath = 'page'  # /blog/page/2/

权重排序

# 权重越小,在排序时越靠前
[languages.zh]
  weight = 1  # 第一位
  
[languages.en]
  weight = 2  # 第二位
  
[languages.ja]
  weight = 3  # 第三位

内容组织策略

目录结构方案

方案一:按语言分目录

content/
├── zh/
│   ├── _index.md
│   ├── about.md
│   └── posts/
│       ├── _index.md
│       ├── post-1.md
│       └── post-2.md
├── en/
│   ├── _index.md
│   ├── about.md
│   └── posts/
│       ├── _index.md
│       ├── post-1.md
│       └── post-2.md
└── ja/
    ├── _index.md
    └── posts/
        └── _index.md

方案二:文件名后缀

content/
├── _index.zh.md
├── _index.en.md
├── about.zh.md
├── about.en.md
└── posts/
    ├── _index.zh.md
    ├── _index.en.md
    ├── post-1.zh.md
    ├── post-1.en.md
    ├── post-2.zh.md
    └── post-2.en.md

内容翻译关联

通过文件名关联

# content/zh/posts/my-post.md
---
title: "我的文章"
date: 2025-06-19
translationKey: "my-post"
---

# content/en/posts/my-post.md
---
title: "My Post"
date: 2025-06-19
translationKey: "my-post"
---

自动关联

Hugo 会自动关联具有相同路径的不同语言版本:

content/
├── zh/
│   └── about.md        # 自动关联
├── en/
│   └── about.md        # 自动关联
└── ja/
    └── about.md        # 自动关联

翻译管理

i18n 翻译文件

创建翻译文件存储字符串翻译:

中文翻译文件

# i18n/zh.yaml
- id: "home"
  translation: "首页"
  
- id: "about"
  translation: "关于"
  
- id: "posts"
  translation: "文章"
  
- id: "read_more"
  translation: "阅读更多"
  
- id: "published_on"
  translation: "发布于"
  
- id: "reading_time"
  translation: "阅读时间"
  other: "{{ .Count }} 分钟"
  
- id: "page_not_found"
  translation: "页面未找到"
  
- id: "search_placeholder"
  translation: "搜索文章..."

英文翻译文件

# i18n/en.yaml
- id: "home"
  translation: "Home"
  
- id: "about"
  translation: "About"
  
- id: "posts"
  translation: "Posts"
  
- id: "read_more"
  translation: "Read More"
  
- id: "published_on"
  translation: "Published on"
  
- id: "reading_time"
  one: "{{ .Count }} minute"
  other: "{{ .Count }} minutes"
  
- id: "page_not_found"
  translation: "Page Not Found"
  
- id: "search_placeholder"
  translation: "Search posts..."

在模板中使用翻译

<!-- 基本翻译 -->
<h1>{{ i18n "home" }}</h1>

<!-- 带参数的翻译 -->
<p>{{ i18n "published_on" . }} {{ .Date.Format "2006-01-02" }}</p>

<!-- 复数形式 -->
<span>{{ i18n "reading_time" .ReadingTime }}</span>

<!-- 带回退的翻译 -->
{{ i18n "custom_key" | default "Default Text" }}

<!-- 检查翻译是否存在 -->
{{ if i18n "optional_key" }}
  <p>{{ i18n "optional_key" }}</p>
{{ end }}

复数规则支持

Hugo 支持不同语言的复数规则:

# i18n/zh.yaml
- id: "items_count"
  other: "{{ .Count }} 个项目"

# i18n/en.yaml  
- id: "items_count"
  one: "{{ .Count }} item"
  other: "{{ .Count }} items"

# i18n/ru.yaml
- id: "items_count"
  one: "{{ .Count }} элемент"
  few: "{{ .Count }} элемента" 
  many: "{{ .Count }} элементов"
  other: "{{ .Count }} элементов"

URL 本地化

路径本地化

通过前置元数据自定义不同语言的 URL:

# content/zh/about.md
---
title: "关于我们"
slug: "guanyu"
url: "/guanyu/"
---

# content/en/about.md
---
title: "About Us"
slug: "about"
url: "/about/"
---

永久链接本地化

# hugo.toml
[languages.zh]
  [languages.zh.permalinks]
    posts = "/wenzhang/:year/:month/:title/"
    
[languages.en]
  [languages.en.permalinks]  
    posts = "/posts/:year/:month/:title/"

别名重定向

# content/zh/about.md
---
title: "关于我们"
aliases:
  - "/about-us/"
  - "/guanyu-women/"
---

# content/en/about.md
---
title: "About Us"
aliases:
  - "/guanyu/"
  - "/about-zh/"
---

日期和数字本地化

日期格式化

<!-- 使用语言特定的日期格式 -->
{{ .Date.Format "2006年01月02日" }}  <!-- 中文 -->
{{ .Date.Format "January 2, 2006" }}  <!-- 英文 -->

<!-- 根据当前语言自动格式化 -->
{{ .Date | dateFormat ":date_medium" }}

数字和货币格式化

<!-- 数字格式化 -->
{{ lang.FormatNumber 2 1234.56 }}

<!-- 货币格式化 -->
{{ lang.FormatCurrency 2 "USD" 123.45 }}

<!-- 百分比格式化 -->
{{ lang.FormatPercent 2 0.1234 }}

自定义格式化函数

<!-- 在模板中定义本地化函数 -->
{{ define "formatPrice" }}
  {{ if eq .Site.Language.Lang "zh" }}
    ¥{{ .price }}
  {{ else if eq .Site.Language.Lang "en" }}
    ${{ .price }}
  {{ else if eq .Site.Language.Lang "ja" }}
    ¥{{ .price }}
  {{ end }}
{{ end }}

<!-- 使用自定义函数 -->
{{ template "formatPrice" (dict "price" 99.99) }}

模板中的多语言功能

语言切换器

<!-- 基本语言切换器 -->
<nav class="language-switcher">
  {{ range .Site.Languages }}
    {{ if eq . $.Site.Language }}
      <span class="current">{{ .LanguageName }}</span>
    {{ else }}
      {{ with $.Translations.Get .Lang }}
        <a href="{{ .Permalink }}">{{ .Language.LanguageName }}</a>
      {{ else }}
        <a href="{{ .BaseURL }}">{{ .LanguageName }}</a>
      {{ end }}
    {{ end }}
  {{ end }}
</nav>

<!-- 高级语言切换器 -->
<div class="language-selector">
  <button class="current-lang">
    {{ .Site.Language.LanguageName }}
  </button>
  <ul class="lang-options">
    {{ range .Site.Languages }}
      {{ if ne . $.Site.Language }}
        <li>
          {{ with $.Translations.Get .Lang }}
            <a href="{{ .Permalink }}" hreflang="{{ .Lang }}">
              {{ .Language.LanguageName }}
            </a>
          {{ else }}
            <a href="{{ .BaseURL }}" hreflang="{{ .Lang }}">
              {{ .LanguageName }}
            </a>
          {{ end }}
        </li>
      {{ end }}
    {{ end }}
  </ul>
</div>

检查翻译可用性

<!-- 检查当前页面是否有其他语言版本 -->
{{ if .Translations }}
  <div class="translations">
    <h3>{{ i18n "other_languages" }}</h3>
    <ul>
      {{ range .Translations }}
        <li>
          <a href="{{ .Permalink }}" hreflang="{{ .Lang }}">
            {{ .Language.LanguageName }}: {{ .Title }}
          </a>
        </li>
      {{ end }}
    </ul>
  </div>
{{ end }}

<!-- 检查特定语言版本 -->
{{ with .Translations.Get "en" }}
  <a href="{{ .Permalink }}">Read in English</a>
{{ end }}

语言特定的模板

<!-- 根据语言加载不同的模板部分 -->
{{ $template := printf "partials/header-%s.html" .Site.Language.Lang }}
{{ if templates.Exists $template }}
  {{ partial $template . }}
{{ else }}
  {{ partial "partials/header.html" . }}
{{ end }}

<!-- 语言特定的样式 -->
{{ if eq .Site.Language.Lang "ar" }}
  <link rel="stylesheet" href="/css/rtl.css">
{{ end }}

SEO 优化

hreflang 标签

<!-- 在 head 中添加 hreflang 标签 -->
<head>
  {{ range .Translations }}
    <link rel="alternate" hreflang="{{ .Lang }}" href="{{ .Permalink }}">
  {{ end }}
  <link rel="alternate" hreflang="{{ .Site.Language.Lang }}" href="{{ .Permalink }}">
  <link rel="alternate" hreflang="x-default" href="{{ .Site.BaseURL }}">
</head>

结构化数据

<!-- 多语言结构化数据 -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "WebPage",
  "name": "{{ .Title }}",
  "description": "{{ .Description }}",
  "inLanguage": "{{ .Site.Language.Lang }}",
  "url": "{{ .Permalink }}",
  {{ if .Translations }}
  "sameAs": [
    {{ range $index, $translation := .Translations }}
      {{ if $index }},{{ end }}
      "{{ $translation.Permalink }}"
    {{ end }}
  ],
  {{ end }}
  "publisher": {
    "@type": "Organization",
    "name": "{{ .Site.Title }}"
  }
}
</script>

部署配置

单主机配置

# hugo.toml - 单主机多语言
baseURL = 'https://example.com'

[languages]
  [languages.zh]
    languageName = '中文'
    weight = 1
    
  [languages.en]
    languageName = 'English'
    weight = 2

URL 结构:

多主机配置

# hugo.toml - 多主机配置
[languages]
  [languages.zh]
    baseURL = 'https://example.com'
    languageName = '中文'
    weight = 1
    
  [languages.en]
    baseURL = 'https://en.example.com'
    languageName = 'English'
    weight = 2
    
  [languages.ja]
    baseURL = 'https://ja.example.com'
    languageName = '日本語'
    weight = 3

环境特定配置

# config/production/hugo.toml
[languages.zh]
  baseURL = 'https://example.com'
  
[languages.en]
  baseURL = 'https://en.example.com'

# config/development/hugo.toml
[languages.zh]
  baseURL = 'http://localhost:1313'
  
[languages.en]
  baseURL = 'http://localhost:1313'

最佳实践

1. 内容管理策略

  • 使用一致的翻译键 (translationKey)
  • 建立内容翻译工作流程
  • 定期审查和更新翻译内容
  • 为每种语言指定负责人

2. 技术实施建议

# 推荐的基础配置
defaultContentLanguage = 'zh'
defaultContentLanguageInSubdir = false
enableMissingTranslationPlaceholders = false

[languages]
  [languages.zh]
    languageName = '中文'
    languageCode = 'zh-CN'
    weight = 1
    
  [languages.en]  
    languageName = 'English'
    languageCode = 'en-US'
    weight = 2

3. 调试和测试

# 启用翻译警告
hugo server --printI18nWarnings

# 检查缺失翻译
grep -r "i18n" layouts/ | grep -v ".git"

# 构建特定语言
hugo --environment production --buildDrafts=false

4. 性能优化

  • 合理组织翻译文件,避免过大的单个文件
  • 使用 Hugo 的缓存机制
  • 考虑为不同语言使用不同的 CDN 分发

通过 Hugo 的多语言支持,您可以构建真正国际化的静态网站,为全球用户提供本地化的体验。

文章导航

章节内容

这是章节的内容页面。

章节概览