从Hexo迁移到Hugo后,我发现了一个默认分类问题,对中文用户造成了一定的影响。

Hugo分类器

Hugo具有自定义Taxonomy(分类器)功能。为了方便用户使用,系统默认提供了两个预设分类:Category(类别)和Tag(标签)供快捷配置1。用户无需手动编写分类器,只需在配置文件中如下填写即可启用两个分类标准。

taxonomies:
  category: catName
  tag: tagName

系统会自动增加两个名为catNametagName的分类标准。然后在文章里的Front Formatter中增加配置

catName:
- name1
- name2
tagName:
- name1
- name2

即可通过访问/catName/tagName查看到两个分类下的所有类别。分类页面标题为设置的catNametagName

中文问题

这个方便的功能对于中文用户来说却存在一个问题。如果我们设置了如下分类标准

taxonomies:
  category: 分类
  tag: 标签

我们需要访问的页面地址,就变成了/分类/标签,在地址栏中并不美观。如果使用英文作为分类名,页面上显示的就不是中文标题,而是英文标题。

对于一些人来说,这或许不是一个问题。但我的博客配置了多语言,在纯中文界面上显示英文标题对我来说不可接受,所以我一直在寻找解决办法。

解决方案一

我首先想到的方案是,为中文单独设置一个分类名称,然后自定义它的显示逻辑。根据官方文档2,Hugo渲染页面时有一套加载顺序,用户自定义配置可新建对应文件。

首先创建一个名称为zhTags的分类名,然后在博客目录下新建layouts/zhTags目录并创建terms.html.html的文件,即可自定义该分类的渲染逻辑。我稍微修改了博客主题paperMod的分类渲染配置,并写死名称为“标签”,如下所示。

{{- define "main" }}

{{- if .Title }}
<header class="page-header">
    <h1>标签</h1>
    {{- if .Description }}
    <div class="post-description">
        {{ .Description }}
    </div>
    {{- end }}
</header>
{{- end }}

<ul class="terms-tags">
    {{- $type := .Type }}
    {{- range $key, $value := .Data.Terms.Alphabetical }}
    {{- $name := .Name }}
    {{- $count := .Count }}
    {{- with site.GetPage (printf "/%s/%s" $type $name) }}
    <li>
        <a href="{{ .Permalink }}">{{ .Name }} <sup><strong><sup>{{ $count }}</sup></strong></sup> </a>
    </li>
    {{- end }}
    {{- end }}
</ul>

{{- end }}{{/* end main */ -}}

看起来解决了中文分类的问题,但是我却并不满意。这个分类器的访问路径是/zh/zhTags,和英文不一致,代码里还写死了名称。有没有办法让中英文使用同一套分类标准,根据语言代码不同,显示不同的名称呢?

解决方案二

Hugo原生支持多语言功能,在又查阅了一遍文档后,我发现了一个好用的函数:lang.Translate3, 只需要配置好多语言,它可以自动按配置渲染不同的内容。

删除原来的配置,统一中英文分类名成为categories,新建layouts/categories目录并创建terms.html.html的文件,内容只需稍作修改。

{{- define "main" }}

{{- if .Title }}
<header class="page-header">
    <h1>{{ lang.Translate .Title }}</h1>
    {{- if .Description }}
    <div class="post-description">
        {{ .Description }}
    </div>
    {{- end }}
</header>
{{- end }}

<ul class="terms-tags">
    {{- $type := .Type }}
    {{- range $key, $value := .Data.Terms.Alphabetical }}
    {{- $name := .Name }}
    {{- $count := .Count }}
    {{- with site.GetPage (printf "/%s/%s" $type $name) }}
    <li>
        <a href="{{ .Permalink }}">{{ .Name }} <sup><strong><sup>{{ $count }}</sup></strong></sup> </a>
    </li>
    {{- end }}
    {{- end }}
</ul>

{{- end }}{{/* end main */ -}}

上述代码仅仅修改了<h1>{{ lang.Translate .Title }}</h1>这一段。

然后根目录下新增翻译配置文件/i18n/zh.yaml/i18n/en.yaml,配置内容分别如下:

Categories: 分类
Tags: 标签
Categories: Categories
Tags: 标签

这样在中文页面中,当标题是Categories时会自动翻译成分类,页面显示终于正常了,不同语言文章也都使用同一个分类器,无需单独创建新的分类。