HUGOを多言語対応にするときの言語切り替えボタンのリンク

目次

はじめに

hugoは多言語対応している静的サイトジェネレーターです。ただそこはやはり静的サイトジェネレーターということで最低限の機能でつくられています。そのため言語切り替えで少し気に入らない点があったのでその記録。

hugo version:hugo v0.111.3+extended linux/amd64 BuildDate=2023-03-16T08:41:31Z VendorInfo=debian:0.111.3-1

theme:mainroad

hugoの多言語対応の概要

ファイルごとに分ける方法とディレクトリごとに分ける方法があります。私の場合はファイルごとに分けています。

ファイルごとにわける→index.mdとindex.en.md を作る。index.mdはデフォルト設定言語になります。

ディレクトリごとに分ける /ja/index.md と /en/index.md をつくります。

ファイルごとに分けるので設定ファイルのhugo.toml/yamlを次のようにします。

DefaultContentLanguage = "ja"

[languages] #多言語設定
  [languages.ja]
   languageName = "Japanese"
   weight = 1
   title="ja"

  [languages.en]
   languageName = "English"
   weight = 2
   title="en"

[Params.sidebar]
 widgets = ["languages","search", "recent", "categories", "taglist", "social","archive"]

他にもスペイン語とか足したい場合は同じようにlanguageNameを設定しましょう。weightは言語の優先度を表していて0以上で小さいほうが優先される設定です。

Params.sidebarはこの通りでなくて大丈夫ですがlanguagesを入れておきましょう。言語の切り替えボタンになります。

詳しくは公式

tomlの設定をした上でindex.mdとindex.en.mdを作るとそれぞれ日本語、英語用として認識され言語切り替えボタンも作られます。楽チンですね。この記事も英語版を作っているので言語ボタンはMainroadをテーマに使うと右のメニュー下(スマホはページ下部)の感じになります。

言語切り替えボタンのリンク

問題なのが言語切り替えボタンはデフォルトだとその記事の英語版(日本語版)ではなく英語版のトップページに言ってしまします。urlとしては /en になってしまいます。これでいい人もいるかもですが直感的にはその記事の英語版にとんでほしいわけです。(この記事のボタンは編集済みなのでこの記事の英語版にとぶはずです。)そこで設定を変更します。

なお以下の操作は設定ファイルを変更するのでバックアップを取るなりしてからやってください。

themes/<テーマ>/layouts/partials/widges/languages.html を開きます。

以下のようなファイルです。

{{- $translations := .Site.Home.AllTranslations }}
{{- if and hugo.IsMultilingual (gt (len $translations) 0) }}

<div class="widget-languages widget">
	<h4 class="widget__title">{{ T "languages_title" }}</h4>
	<div class="widget__content">
		<ul class="widget__list">
			{{- range $translations }}
			<li class="widget__item">
				<a class="widget-languages__link widget__link" href="{{ .RelPermalink }}">
					<span class="widget-languages__link-btn widget__link-btn btn">{{ .Language | upper }}</span>
					{{- with .Language.LanguageName }}
					<span class="widget-languages__link-text widget__link-text">{{ . | title | humanize }}</span>
					{{- end }}
				</a>
			</li>
			{{- end }}
		</ul>
	</div>
</div>
{{- end }}

このファイルを次のように変更します。全文です。

{{- $currentPage := . }} <!-- 現在のページを取得 -->
{{- $translations := $currentPage.AllTranslations }} <!-- 現在のページのすべての翻訳を取得 -->

{{- if and hugo.IsMultilingual (gt (len $translations) 1) }}
<div class="widget-languages widget">
    <h4 class="widget__title">{{ T "languages_title" }}</h4>
    <div class="widget__content">
        <ul class="widget__list">
            {{- range $translations }}
            <li class="widget__item">
                <a class="widget-languages__link widget__link" href="{{ .RelPermalink }}">
                    <span class="widget-languages__link-btn widget__link-btn btn">{{ .Language | upper }}</span>
                    {{- with .Language.LanguageName }}
                    <span class="widget-languages__link-text widget__link-text">{{ . | title | humanize }}</span>
                    {{- end }}
                </a>
            </li>
            {{- end }}
        </ul>
    </div>
</div>
{{- end }}

そうしたら複数言語作成したページには言語切り替えボタンが作られてリンクはそのページの他言語版になっています。

詳しく知りたい人向け

まずchatGPTに書かせているのですべてを理解しているわけではありませんということを先に言っておきます。(保険)

変更点は

{{- $currentPage := . }} <!-- 現在のページを取得 -->
{{- $translations := $currentPage.AllTranslations }} <!-- 現在のページのすべての翻訳を取得 -->

{{- if and hugo.IsMultilingual (gt (len $translations) 1) }}

↑です。既存の設定だとサイト全体で他言語ページが1つでもあれば言語切り替えボタンを作っていたのでそれをやめて現在のページに翻訳版があるかを取得しています。そのうえで言語設定が1より大きい(=複数言語作ってる)ときのみ表示しています。0を1に変えただけです。

これでリンク先も変わる仕組みは具体的にリンク先を指定している↓がポイントです。

<a class="widget-languages__link widget__link" href="{{ .RelPermalink }}">

既存の設定は$translationsにサイト全体から取得した翻訳版の情報を入れるためリンク情報の.RelPermalinkがサイトのトップになってしまっていました。これを今のページに変えることで.RelPermalinkも今のページ基準になるのでリンク先が変わっています。

まあ全部chatgptがやったようなもんですが。

まとめ

ということで言語切り替えボタンの改善設定でした。このブログは基本的には日本語だけですが他のサイトで必要になりそうだったのでやりました。一応このページだけはテスト用に多言語対応しています。