HUGO
Menu
GitHub 87548 stars Mastodon

Hugo 多语言模式

为每种语言和区域本地化你的项目,包括翻译、图像、日期、货币、数字、百分比和排序顺序。Hugo 的多语言框架支持单主机和多主机配置。

配置

请参阅 configure languages

翻译内容

有两种方法可以管理内容翻译。两种方法都确保每个页面都分配了语言并链接到其对应的翻译。

按文件名翻译

考虑以下示例:

  1. /content/about.en.md
  2. /content/about.fr.md

第一个文件分配了英语并链接到第二个。 第二个文件分配了法语并链接到第一个。

它们的语言根据添加到文件名的语言代码后缀分配。

通过具有相同的路径和基本文件名,内容片段作为翻译页面链接在一起。

如果文件没有语言代码,将分配默认语言。

按内容目录翻译

此系统为每种语言使用不同的内容目录。每种语言的 content 目录使用 contentDir 参数设置。

languages:
  en:
    contentDir: content/english
    languageName: English
    weight: 10
  fr:
    contentDir: content/french
    languageName: Français
    weight: 20
[languages]
  [languages.en]
    contentDir = 'content/english'
    languageName = 'English'
    weight = 10
  [languages.fr]
    contentDir = 'content/french'
    languageName = 'Français'
    weight = 20
{
   "languages": {
      "en": {
         "contentDir": "content/english",
         "languageName": "English",
         "weight": 10
      },
      "fr": {
         "contentDir": "content/french",
         "languageName": "Français",
         "weight": 20
      }
   }
}

contentDir 的值可以是任何有效的路径——甚至是绝对路径引用。唯一的限制是内容目录不能重叠。

考虑以下示例与上面的配置结合:

  1. /content/english/about.md
  2. /content/french/about.md

第一个文件分配了英语并链接到第二个。 第二个文件分配了法语并链接到第一个。

它们的语言根据它们放置的 content 目录分配。

通过具有相同的路径和基本名称(相对于它们的语言 content 目录),内容片段作为翻译页面链接在一起。

绕过默认链接

任何共享相同 translationKey(在 front matter 中设置)的页面都将作为翻译页面链接,无论基本名称或位置如何。

考虑以下示例:

  1. /content/about-us.en.md
  2. /content/om.nn.md
  3. /content/presentation/a-propos.fr.md
translationKey: about
translationKey = 'about'
{
   "translationKey": "about"
}

通过在所有三个页面中将 translationKey front matter 参数设置为 about,它们将作为翻译页面链接。

本地化永久链接

因为使用路径和文件名来处理链接,所有翻译页面将共享相同的 URL(除了语言子目录)。

要本地化 URL:

  • 对于常规页面,在 front matter 中设置 slugurl
  • 对于 section 页面,在 front matter 中设置 url

例如,法语翻译可以有自己的本地化 slug。

---
slug: a-propos
title: A Propos
---
+++
slug = 'a-propos'
title = 'A Propos'
+++
{
   "slug": "a-propos",
   "title": "A Propos"
}

在渲染时,Hugo 将构建 /about//fr/a-propos/ 而不影响翻译链接。

页面 bundle

为了避免复制文件的负担,每个 Page Bundle 继承其链接的翻译页面的 bundle 的资源,内容文件(Markdown 文件、HTML 文件等)除外。

因此,在模板中,页面将可以访问所有链接页面的 bundle 的文件。

如果在链接的 bundle 中,两个或多个文件共享相同的基本名称,则只包含一个文件,选择如下:

  • 如果存在,来自当前语言 bundle 的文件。
  • 按语言 Weight 顺序在 bundle 中找到的第一个文件。

Page Bundle 资源遵循与内容文件相同的语言分配逻辑,按文件名(image.jpgimage.fr.jpg)和目录(english/about/header.jpgfrench/about/header.jpg)。

引用翻译内容

要创建翻译内容链接列表,使用类似以下的模板:

layouts/_partials/i18nlist.html
{{ if .IsTranslated }}
<h4>{{ i18n "translations" }}</h4>
<ul>
  {{ range .Translations }}
  <li>
    <a href="{{ .RelPermalink }}">{{ .Language.Lang }}: {{ .LinkTitle }}{{ if .IsPage }} ({{ i18n "wordCount" . }}){{ end }}</a>
  </li>
  {{ end }}
</ul>
{{ end }}

上面可以放在 partial 模板中,然后包含在任何模板中。如果给定页面没有翻译,它将不打印任何内容。

上面还使用了下一节中描述的 i18n function

列出所有可用语言

Page 上的 .AllTranslations 可用于列出所有翻译,包括页面本身。在首页上,它可用于构建语言导航器:

layouts/_partials/allLanguages.html
<ul>
{{ range $.Site.Home.AllTranslations }}
<li><a href="{{ .RelPermalink }}">{{ .Language.LanguageName }}</a></li>
{{ end }}
</ul>

字符串翻译

请参阅 lang.Translate 模板函数。

本地化

以下本地化示例假设站点的主要语言是英语,翻译为法语和德语。

defaultContentLanguage: en
languages:
  de:
    contentDir: content/de
    languageName: Deutsch
    weight: 3
  en:
    contentDir: content/en
    languageName: English
    weight: 1
  fr:
    contentDir: content/fr
    languageName: Français
    weight: 2
defaultContentLanguage = 'en'
[languages]
  [languages.de]
    contentDir = 'content/de'
    languageName = 'Deutsch'
    weight = 3
  [languages.en]
    contentDir = 'content/en'
    languageName = 'English'
    weight = 1
  [languages.fr]
    contentDir = 'content/fr'
    languageName = 'Français'
    weight = 2
{
   "defaultContentLanguage": "en",
   "languages": {
      "de": {
         "contentDir": "content/de",
         "languageName": "Deutsch",
         "weight": 3
      },
      "en": {
         "contentDir": "content/en",
         "languageName": "English",
         "weight": 1
      },
      "fr": {
         "contentDir": "content/fr",
         "languageName": "Français",
         "weight": 2
      }
   }
}

日期

使用此 front matter:

date: 2021-11-03T12:34:56+01:00
date = 2021-11-03T12:34:56+01:00
{
   "date": "2021-11-03T12:34:56+01:00"
}

使用此模板代码:

{{ .Date | time.Format ":date_full" }}

渲染的页面显示:

Language Value
English Wednesday, November 3, 2021
Français mercredi 3 novembre 2021
Deutsch Mittwoch, 3. November 2021

有关详细信息,请参阅 time.Format

货币

使用此模板代码:

{{ 512.5032 | lang.FormatCurrency 2 "USD" }}

渲染的页面显示:

Language Value
English $512.50
Français 512,50 $US
Deutsch 512,50 $

有关详细信息,请参阅 lang.FormatCurrencylang.FormatAccounting

数字

使用此模板代码:

{{ 512.5032 | lang.FormatNumber 2 }}

渲染的页面显示:

Language Value
English 512.50
Français 512,50
Deutsch 512,50

有关详细信息,请参阅 lang.FormatNumberlang.FormatNumberCustom

百分比

使用此模板代码:

{{ 512.5032 | lang.FormatPercent 2 }}

渲染的页面显示:

Language Value
English 512.50%
Français 512,50 %
Deutsch 512,50 %

有关详细信息,请参阅 lang.FormatPercent

菜单

菜单条目的本地化取决于你如何定义它们:

  • 当你使用 section 页面菜单 automatically 定义菜单条目时,你必须使用翻译表来本地化每个条目。
  • 当你 in front matter 定义菜单条目时,它们已经根据 front matter 本身本地化。如果 front matter 值不足,使用翻译表来本地化每个条目。
  • 当你 in site configuration 定义菜单条目时,你必须在每个语言键下创建特定语言的菜单条目。如果菜单条目的名称不足,使用翻译表来本地化每个条目。

创建特定语言的菜单条目

方法 1 – 使用单个配置文件

对于具有少量条目的简单菜单,使用单个配置文件。例如:

languages:
  de:
    languageCode: de-DE
    languageName: Deutsch
    menus:
      main:
      - name: Produkte
        pageRef: /products
        weight: 10
      - name: Leistungen
        pageRef: /services
        weight: 20
    weight: 1
  en:
    languageCode: en-US
    languageName: English
    menus:
      main:
      - name: Products
        pageRef: /products
        weight: 10
      - name: Services
        pageRef: /services
        weight: 20
    weight: 2
[languages]
  [languages.de]
    languageCode = 'de-DE'
    languageName = 'Deutsch'
    weight = 1
    [languages.de.menus]
      [[languages.de.menus.main]]
        name = 'Produkte'
        pageRef = '/products'
        weight = 10
      [[languages.de.menus.main]]
        name = 'Leistungen'
        pageRef = '/services'
        weight = 20
  [languages.en]
    languageCode = 'en-US'
    languageName = 'English'
    weight = 2
    [languages.en.menus]
      [[languages.en.menus.main]]
        name = 'Products'
        pageRef = '/products'
        weight = 10
      [[languages.en.menus.main]]
        name = 'Services'
        pageRef = '/services'
        weight = 20
{
   "languages": {
      "de": {
         "languageCode": "de-DE",
         "languageName": "Deutsch",
         "menus": {
            "main": [
               {
                  "name": "Produkte",
                  "pageRef": "/products",
                  "weight": 10
               },
               {
                  "name": "Leistungen",
                  "pageRef": "/services",
                  "weight": 20
               }
            ]
         },
         "weight": 1
      },
      "en": {
         "languageCode": "en-US",
         "languageName": "English",
         "menus": {
            "main": [
               {
                  "name": "Products",
                  "pageRef": "/products",
                  "weight": 10
               },
               {
                  "name": "Services",
                  "pageRef": "/services",
                  "weight": 20
               }
            ]
         },
         "weight": 2
      }
   }
}

方法 2 – 使用配置目录

对于更复杂的菜单结构,创建 configuration directory 并将菜单条目拆分为多个文件,每种语言一个文件。例如:

config/
└── _default/
    ├── menus.de.toml
    ├── menus.en.toml
    └── hugo.toml
main:
- name: Produkte
  pageRef: /products
  weight: 10
- name: Leistungen
  pageRef: /services
  weight: 20
[[main]]
  name = 'Produkte'
  pageRef = '/products'
  weight = 10
[[main]]
  name = 'Leistungen'
  pageRef = '/services'
  weight = 20
{
   "main": [
      {
         "name": "Produkte",
         "pageRef": "/products",
         "weight": 10
      },
      {
         "name": "Leistungen",
         "pageRef": "/services",
         "weight": 20
      }
   ]
}
main:
- name: Products
  pageRef: /products
  weight: 10
- name: Services
  pageRef: /services
  weight: 20
[[main]]
  name = 'Products'
  pageRef = '/products'
  weight = 10
[[main]]
  name = 'Services'
  pageRef = '/services'
  weight = 20
{
   "main": [
      {
         "name": "Products",
         "pageRef": "/products",
         "weight": 10
      },
      {
         "name": "Services",
         "pageRef": "/services",
         "weight": 20
      }
   ]
}

使用翻译表

当渲染每个菜单条目中显示的文本时,example menu template 执行以下操作:

{{ or (T .Identifier) .Name | safeHTML }}

它使用菜单条目的 identifier 查询当前语言的翻译表并返回翻译的字符串。如果翻译表不存在,或者翻译表中不存在 identifier 键,它将回退到 name

identifier 取决于你如何定义菜单条目:

例如,如果你在站点配置中定义菜单条目:

menus:
  main:
  - identifier: products
    name: Products
    pageRef: /products
    weight: 10
  - identifier: services
    name: Services
    pageRef: /services
    weight: 20
[menus]
  [[menus.main]]
    identifier = 'products'
    name = 'Products'
    pageRef = '/products'
    weight = 10
  [[menus.main]]
    identifier = 'services'
    name = 'Services'
    pageRef = '/services'
    weight = 20
{
   "menus": {
      "main": [
         {
            "identifier": "products",
            "name": "Products",
            "pageRef": "/products",
            "weight": 10
         },
         {
            "identifier": "services",
            "name": "Services",
            "pageRef": "/services",
            "weight": 20
         }
      ]
   }
}

在翻译表中创建相应的条目:

products: Produkte
services: Leistungen
products = 'Produkte'
services = 'Leistungen'
{
   "products": "Produkte",
   "services": "Leistungen"
}

缺失的翻译

如果字符串没有当前语言的翻译,Hugo 将使用默认语言的值。如果没有设置默认值,将显示空字符串。

在翻译 Hugo 网站时,能够有缺失翻译的视觉指示器可能很方便。enableMissingTranslationPlaceholders configuration option 将用占位符 [i18n] identifier 标记所有未翻译的字符串,其中 identifier 是缺失翻译的 id。

Hugo 将使用这些缺失翻译占位符生成你的网站。它可能不适合生产环境。

对于合并来自其他语言的内容(即缺失的内容翻译),请参阅 lang.Merge

要追踪缺失的翻译字符串,使用 --printI18nWarnings 标志运行 Hugo:

hugo --printI18nWarnings | grep i18n
i18n|MISSING_TRANSLATION|en|wordCount

多语言主题支持

要在主题中支持多语言模式,必须考虑模板中的 URL。如果有多种语言,URL 必须满足以下条件:

  • 来自内置的 .Permalink.RelPermalink
  • 使用 relLangURLabsLangURL 模板函数构建,或前缀为 {{ .LanguagePrefix }}

如果定义了多种语言,LanguagePrefix 方法将返回 /en(或当前语言)。如果未启用,它将是空字符串(因此对单语言 Hugo 网站无害)。

使用 hugo new content 生成多语言内容

如果你在同一目录中组织有翻译的内容:

hugo new content post/test.en.md
hugo new content post/test.de.md

如果你在不同目录中组织有翻译的内容:

hugo new content content/en/post/test.md
hugo new content content/de/post/test.md

Last updated: January 1, 0001
Improve this page