Hugo多语言标签:统一管理,避免不一致

30 阅读3分钟

在Hugo多语言博客中使用标签时,我发现了两个问题。

多语言显示——希望中文页面显示「测试」,英语页面显示「Testing」。

命名不一致——如果在每种语言的front matter中直接写标签名,很容易出现偏差。英语里「e-mail」「email」「Email」混用,中文里「数据库」「资料库」难以统一。靠人工维护,很难保持一致。

下面介绍一个能同时解决这两个问题的方案。

整理需求

先明确我想实现什么:

  • 按读者的语言显示标签
  • 在一个地方统一管理
  • 添加新标签时,不遗漏任何语言版本

在front matter中直接写标签名,可以满足第一个需求,但后两个就难了。文章越多,不一致的风险越大。

方案:用data/tags.yaml集中管理

最终我选择了这样做。

front matter只写英语slug:

# front matter(所有语言通用)
tags:
  - testing

翻译放在data/tags.yaml,所有语言写在一起:

testing:
  zh: 测试
  en: Testing
  ja: テスト

模板根据当前语言获取对应的显示名。

因为front matter在所有语言中完全相同,自然就不会出现不一致。翻译集中在一个文件里,有没有遗漏一目了然。

为什么用data/tags.yaml而不是i18n文件夹?

Hugo有标准的i18n功能,按语言分成多个文件:i18n/ja.yamli18n/en.yaml等等。

两种方式都需要修改模板。用i18n功能确实更「Hugo风格」一些。

但我选择了data/tags.yaml

原因是可见性。

用i18n文件夹的话,每次添加标签都要编辑多个文件。想确认某个标签在其他语言里怎么翻译的,要逐个文件去找。

data/tags.yaml,所有标签×所有语言都在一个文件里。添加、确认,全在一个地方完成。

还有一个好处:方便给AI提供上下文。让AI帮忙添加标签时,只需要传这一个文件。

实现

data/tags.yaml

创建标签主数据:

# data/tags.yaml
testing:
  ja: テスト
  en: Testing
  zh: 测试

rails:
  ja: Rails
  en: Rails
  zh: Rails

有些标签各语言写法相同,有些不同。无论哪种,结构都一样。

翻译用的partial

创建layouts/partials/tag-name.html

{{- $tagKey := .tagKey | lower -}}
{{- $tagData := index site.Data.tags $tagKey -}}

{{- if not $tagData -}}
  {{- errorf "Unknown tag '%s' - add to data/tags.yaml" $tagKey -}}
{{- end -}}

{{- $translated := index $tagData site.Language.Lang -}}
{{- if not $translated -}}
  {{- errorf "Missing translation for tag '%s' (lang: %s)" $tagKey site.Language.Lang -}}
{{- end -}}

{{- $translated -}}

关键是errorf。标签未定义或翻译缺失时,构建会失败。问题立刻就能发现。

覆盖主题模板

在主题目录下用grep找到处理标签的文件:

grep -r "tags" themes/your-theme/layouts/

把相关文件复制到项目的layouts/目录下,保持相同的目录结构。Hugo会优先使用项目级的文件,主题本身不用改动。

在复制的文件中找到显示标签名的地方,替换成这个partial调用:

{{ partial "tag-name.html" (dict "tagKey" .) }}

不同主题的结构不同,但做法是一样的。

总结

front matter统一用英语slug,翻译用data/tags.yaml集中管理。多语言显示和命名统一,两个问题一起解决。

加上构建时的错误检测,翻译遗漏也能及时发现。

标准的i18n文件夹方式也可以,但对于标签来说,我觉得单文件方案更清晰,和AI配合也更顺畅。

原文: sijiaoh.com/zh/posts/hu…