Hugoサイトで多言語対応する
要約: Hugo多言語ブログでbaseURL、sitemap、robots、JSON-LD、Open Graph、meta descriptionを設定し、hreflang・canonicalで重複コンテンツ問題を防ぐ方法をまとめました。slug・translationKeyのトラブルシューティングまで一度に確認できます。

目的
Hugoブログに多言語対応とSEO最適化を適用し、検索エンジンへの露出を最大化するとともに、多言語ユーザーに適切な言語バージョンを提供します。
SEO設定
SEO(Search Engine Optimization、検索エンジン最適化)とは、Googleなどの検索エンジンがサイトのコンテンツを正しく理解し、検索結果に表示できるように、サイト構造とメタデータを最適化する作業です。
この文書では、ブログに適用されたSEO設定をまとめます。
1. 絶対URL - Hugo baseURL設定
- ファイル:
hugo/hugo.toml - 内容:
baseURL = 'https://blog.plzhans.com' - sitemap.xml、RSSフィード、Open Graphなどで正しい絶対URLが生成されます
- Sitemap (
sitemap.xml)、RSSフィード (index.xml) はHugoが自動生成します hugo server(開発時)では自動的にlocalhost:1313を使用するため、別途の処理は不要です
2. robots.txtの自動生成
- ファイル:
hugo/hugo.toml - 内容:
enableRobotsTXT = true - Hugoビルド時に
robots.txtが自動生成されます(すべてのクローラーを許可 + Sitemap URLを含む)
3. Schema.org構造化データ(JSON-LD)
- ファイル:
hugo/layouts/_default/single.html - 記事ページ(
type != "page")にBlogPostingのJSON-LDを挿入します - 含まれる項目: headline、datePublished、dateModified、author、description、mainEntityOfPage
- Google検索結果でリッチスニペット(作成者、日付など)を表示できます
4. og:image(代表画像) / Open Graph
- ファイル:
src/services/NotionExportService.mjs - Notion同期時にコンテンツ内の最初の画像を検出し、front matterの
imagesフィールドに自動追加します - Open Graphメタタグは、Hugo内蔵テンプレート(
_internal/opengraph.html)によって出力され、imagesをog:imageとして使用します
5. meta description / Twitter Card
- ファイル:
src/services/NotionExportService.mjs - Notionの「要約」プロパティをfront matterの
descriptionフィールドとして出力します - Hugo内蔵のopengraph/twitter_cardsテンプレートおよびbaseof.htmlのmeta descriptionで使用されます
- Twitter Cardのメタタグは、Hugo内蔵テンプレート(
_internal/twitter_cards.html)によって出力されます - その他のメタタグ(author、viewport)もテーマがデフォルトで提供します
6. Canonical URL
- ファイル:
hugo/layouts/_default/baseof.html - テーマ(
m10c)のbaseof.htmlをオーバーライドして<link rel="canonical">タグを追加します .Permalinkをcanonical URLとして使用します- 多言語hreflangタグも一緒に含まれます(翻訳ページが存在する場合、
alternate+x-defaultを出力)
7. Google Analytics(GA4)
- テーマ(
m10c)でデフォルト提供されます - Google Search Console認証時にGA連携で認証可能です
多言語SEOの主要要素
HTML lang属性
ページの言語を明示することで、検索エンジンとスクリーンリーダーに言語情報を提供します。
1<html lang="ko">
link rel alternate hreflang
各言語ごとのページURLを検索エンジンに伝えることで、重複コンテンツの問題を防ぎます。
1<link rel="alternate" hreflang="ko" href="https://blog.plzhans.com/ko/post/example/">
2<link rel="alternate" hreflang="en" href="https://blog.plzhans.com/en/post/example/">
3<link rel="alternate" hreflang="ja" href="https://blog.plzhans.com/ja/post/example/">
4<link rel="alternate" hreflang="x-default" href="https://blog.plzhans.com/ko/post/example/">
Canonical URL(多言語)
各言語をプロの翻訳として作成した場合、canonicalを省略することで、すべての言語バージョンを独立したオリジナルとして認めてもらうことができます。
1<link rel="canonical" href="https://blog.plzhans.com/ko/post/example/">
Hugoでの多言語実装
1. テーマの多言語対応の確認
lang属性の確認(themes/{テーマ}/layouts/_default/baseof.html)
1<!doctype html>
2<html lang=" .Site.Language.Lang ">
relLangURL対応の確認
ホームリンクが言語別URLを維持しているかを確認します。対応していない場合はbaseof.htmlをオーバーライドします。
1<body>
2 <header class="app-header">
3 <a href=" .Site.Home.RelPermalink "><img class="app-header-avatar" src="..." alt="..." /></a>
2. hugo.tomlの多言語設定
1# デフォルトのコンテンツ言語
2defaultContentLanguage = "ko"
3# デフォルト言語もサブディレクトリに含める(/ko/)
4defaultContentLanguageInSubdir = true
5
6[languages]
7 [languages.ko]
8 weight = 1
9 languageName = "한국어"
10
11 [languages.en]
12 weight = 2
13 languageName = "English"
14
15 [languages.ja]
16 weight = 3
17 languageName = "日本語"
3. canonicalタグの追加
テーマが対応していない場合はbaseof.htmlをオーバーライドします。
1<link rel="canonical" href=" .Permalink " />
4. hreflangタグの生成
コンテンツファイルにtranslationKeyを設定
1---
2id: "80"
3translationKey: "80"
4slug: "80-redis-dump-vs-aof"
5title: "Redis dump vs aof"
6---
baseof.htmlにhreflangを追加(テーマが対応していない場合はオーバーライド)
1<link rel="alternate" hreflang=" .Language.Lang " href=" .Permalink " />
2<link rel="alternate" hreflang="x-default" href=" .Permalink " />
トラブルシューティング
URLの重複衝突
Hugoで投稿のアドレスを設定する際は、urlではなくslugを使用する必要があります。
原因
slugで設定すると、/ko/、/en/などの言語プレフィックスが自動的に追加されますurlで強制指定すると、Hugoは言語コードを自動的に追加しませんurlを使用する場合、/ko/post/example、/en/post/exampleのように、各言語ごとにURL自体に言語コードを直接入れる必要がありますurlに言語コードなしで同じパスを指定すると、異なる言語の投稿が同じURLを持つことになり、衝突が発生します
解決方法
urlの代わりにslugを使用するように切り替えますhugo.tomlでdefaultContentLanguageInSubdir = trueを設定し、デフォルト言語を含むすべての言語がサブディレクトリ構造を持つようにします
参考
slugだけを指定すると言語コードは自動的に追加されますが、slug自体が特定の言語で書かれている場合は、言語ごとに翻訳する必要があります。slugは英語で作成することを推奨します。
translationKeyを追加したのにhreflangが生成されない
原因
- テーマがhreflangタグの生成に対応していません。
解決方法
- baseof.htmlにhreflang関連のコードをオーバーライドして追加します