Zolaで多言語・SEO対応ブログ・ドキュメントサイトを始めました (3/3)

前々回から、zolaを使って多言語・SEO対応のウェブサイトを構築した話を続けてきました。

前回の話

今回はとりあえずの最終回として、前回インストールしたadidoks(zolaのテーマ)に修正を加えて、多言語・SEO対応を完成させます。

まずadidoksというzolaのテーマは、hugoで人気のdoksというテーマを Aaran Xuさん がzolaに移植されたものです。

現在githubではstarが131で、zola界隈としては5本の指に入る人気のテーマと言っていいでしょう。”SEO-ready”と書いてありますから、SEOも安心なはず(だったのですが…

当初の私の見込みとしては、言語の切り替えが用意されていないadidoksに、英語・日本語切り替えのボタンを適当に付け足せば十分かなと考えていて、あとはいらないファイルをバサバサ削除してやれば、私が作りたいサイトを簡単に作れるだろうと思っていました。

日本語・英語切り替えのためのページ情報の取得

zolaはhugoと同じように多言語サイト作成に対応しています。つまりzolaの設定ファイルconfig.tomlでデフォルト言語が英語の時、

default_language = "en"

content/docsディレクトリ内のmarkdown原稿が

sample.md
sample.ja.md

と配置されている場合、sample.mdが英語用の原稿で、sample.ja.mdが日本語用原稿と判断してzolaは処理します。urlとしては site名/docs/sample/ が英語用、site名/ja/docs/sample/ が日本語用のパスになります。

page.translations か section.translations に多言語情報が格納される

zolaの生成するhtmlページは、セクションとページに大別されます。私のサイトでいうと、ページとは普通のページで、セクションとは ページのリストページ です。zolaはテンプレート処理中、ページの場合はpage変数、セクションの場合はsection変数が、テンプレート処理に渡されます。これらの変数にはページのタイトルや発行日など、ページ・セクションのメタ情報が格納されています。

Sections and Pages | Zola
Everything you need to make a static site engine in one binary.

このドキュメントにあるように、page変数はpage.translationsに、section変数はsection.translationsに多言語情報を配列として格納していて、配列の各アイテムが lang, title, permalink, path の情報を持っています。これらをもとにhtmlのヘッダーに英語・日本語の切り替えスイッチを表示させれば、言語切り替えに対応できます。

日本語・英語切り替えのためのテーマ修正の概略

base.htmlテンプレートの冒頭で必要な変数を定義

いろいろ修正を分散させると面倒なので、自分が独自に使いそうな変数はtemplate/base.htmlの冒頭で全部定義することにしました。概略(なので多少間違いが含まれるかも)を示すと

{% if page -%}
   {% set yg_section_path = page.ancestors | last -%}
   {% set yg_section = get_section(path=yg_section_path) -%}
   {% set yg_translations = page.translations -%}
{% elif section -%}
   {% set yg_section = section -%}
   {% set yg_translations = section.translations -%}
{% else -%} {# 404.html用の処理 -#}
   {% set yg_section = get_section(path="_index.md") -%}
   {% set yg_translations = false -%}
{% endif -%}

{% set yg_anothertrans = false -%}
{% if yg_translations.1 -%} {# 日英の2つの言語がある場合、yg_translationsは2つの要素を持つ -#}
   {% if yg_translations.0.lang == lang -%} {# langは処理中のページの言語 -#}
      {% set yg_anothertrans = yg_translations.1 -%}
   {% else -%}
      {% set yg_anothertrans = yg_translations.0 -%}
   {% endif -%}
{% endif -%}

これをtemplate/base.html の冒頭に書き込めば、セクションページに対しては

  • yg_section, セクションの情報
  • yg_anothertrans, 切り替えが不可能ならfalse、切り替え可能なら切り替え先のセクションの情報(lang, title, permalink, path)

が定義されます。普通のページでは

  • yg_section, ページが所属するセクション のセクション情報
  • yg_anothertrans, 切り替えが不可能ならfalse、切り替え可能なら切り替え先の ページ の情報(lang, title, permalink, path)

が定義されます。

header.html (マクロ)に必要な変数を渡す

docs/sample.mdやdocs/sample.ja.mdを処理するテンプレートは、通常はtemplate/docs/page.htmlに置きます。このpage.htmlはtemplate/base.htmlを継承して拡張したものなので、base.htmlの冒頭の改変は page.htmlにも引き継がれています。

つまり、content/docs/sample.mdやcontent/docs/sample.ja.mdの処理中、template/docs/page.htmlがテンプレートとして利用され、その冒頭でyg_sectionとyg_anothertransが定義されます。

ページのヘッダーはtemplate/macros/header.htmlというマクロをpage.htmlが呼び出すことで作成されています。yg_sectionとyg_anothertransをこのマクロに送るため、page.html内のマクロ呼び出しコードを以下のように改変します。

  {{ macros_header::header(current_section=current_section, yg_section=yg_section, yg_anothertrans=yg_anothertrans)}}

呼ばれる側のtemplate/macros/header.htmlも、マクロの引数定義を書き加えます。

{% macro header(current_section, yg_section=false, yg_anothertrans=false) %}

最後にtemplate/macros/header.html内の適当な場所に、yg_anothertransがfalseでないときだけ、切り替えボタンを表示コードを追加します。例えばこんな感じのリンクです。

{% if yg_anothertrans %}
<a href="{{ yg_anothertrans.permalink | safe }}">
  {{- yg_anothertrans.lang | capitalize -}}
</a>
{% endif %}

なお、yg_sectionは言語切り替えボタンの設置だけを考えるならheader.html(マクロ)に送る必要はありません。ただ、ヘッダーの他の部分の表示でセクション情報が必要で、多言語でこのセクション情報を取り入れるのがいろいろ面倒くさいことになっているので、page.html側で事前に用意したyg_sectionをheader.html(マクロ)に送ってしまうことにしました。

これまで説明したのは普通のページ用のテンプレート(template/docs/page.html)の修正でしたが、セクションページ(docs/_index.md や docs/_index.ja.md)に対応するテンプレートの template/docs/section.html からもheader.html(マクロ)が呼ばれているので、上と同じ様に修正する必要があります。

SEO対応が壊れていた

これまでの修正に加え、さらに諸々の修正を行い、表面上は当初私が目指したページをおおむね生成できるようになりました。とはいえ、もともとadidoksのデモサイトから修正を加えて作ったものですから、htmlファイルの細かいところでadidoksの初期設定が残ってしまうのが心配でした。特に気になるのが次のようなSEO対応のデータです。

  • twitter-card, twitter:title 等のtwitter card向けmetaデータ
  • og:titleやog:description 等のopen graph protocolのmetaデータ (ブログカード等に影響)
  • google等の検索システムが読み取るjson-ldと呼ばれる構造化データ

それでHTMLファイルの中身を直に表示して、詳しく目視でソースを確認しました。それで運良く気づけたのですが…JSON-LDが壊れていました。

具体的には

  • blog記事用のjson-ldのアイキャッチ画像の指定部分が、”image”: , となっていて、jsonファイルとして呼び込めなくなっていた。
  • パンくずリスト用のjson-ldで “itemListElement”: [ が欠落。

この部分の問題はページのぱっと見からは全く判断がつかないのが怖いところです。こういうパターンでhtml内に欠陥が残されたまま公開されてるウェブページは世の中にたくさんありそうですが、json-ldの欠陥はサーチエンジンの検索順位に大きく影響する場合もあるでしょう(今回の場合はデータがうまく壊れていてjson-ldとして認識されないので、逆に大きな問題にならないかもしれませんが)

問題の修正ですが、SEO関係の設定がtemplate/macros/head.htmlというマクロ内部にあるので、そのあたりを適当にいじり、それっぽいjsonが出てくるように調整しました。twitter:imageやog:imageに設定されるアイキャッチ画像も、front matter(markdownファイルの冒頭部分のメタデータ)で

[extra]
eyecatch =   アイキャッチ画像へのパス

と書くだけで簡単に指定できるように書き換えました(これはマクロ内部からpage.extra.eyecatchとかsection.extra.eyecatchとして参照できます)

WordPressが吐くhtmlも参考にしながら、それっぽいSEOデータが出てくるようにhead.htmlを調整したのですが、OGPやJSON-LDの規約を細かく理解する根性はなかったので… 最終的には次のような確認サイトで、それなりの表示になることでよしとしました。自分の作ったページのSEOデータについて気になる方は、これらのサイトで確認してみると良いのではないかと思います。

SEO関係のデータが確認できるサイト

twitterやogpデータの確認

OGP確認:facebook、twitter、LINE、はてなのシェア時の画像・文章を表示 | ラッコツールズ🔧
URLを入力すると各SNS(facebook・twitter・はてなブックマーク・LINE)でページをシェアした際のOGP画像・タイトル・説明文を確認できるOGPデバッガー・シミュレーター。PC版・スマートフォン版・アプリ版で表示サイズ・表...

json-ldの確認

リッチリザルト テスト - Search Console ヘルプ
ページに構造化データを実装して Google 検索結果の特別な機能を有効にすると、リッチリザルトのテストを行うことができます。

macでフォントの表示がおかしくなる

以上のようにSEO関連でひとしきりもめた後、さすがにこれ以上はまることもないだろうと思いつつ、何気なく古いmacのchromeでデザインを確認したところまたまた問題勃発! macで”A”のフォント表示がおかしいことに気づきました。

口でいうのは難しいので、こちらを見てください

Inter – Capital 'A' not showing correctly on Mac OS · Issue #2602 · google/fonts
The capital 'A' isn't displaying correctly. I've researched the issue further and it seems that it displays fine on Chro...

最初はそういうデザインなのかと思ったのですが、デザインにしてはなんかダサいよなぁ…と疑ってみたら、mac限定の問題でした。これはうちのmacが古すぎるからこうなるのかと疑いつつ(使ってるchromeは最新なのですが) firefoxでも再現するので、macのフォントのレンダリングの問題かと思われます。

adidoksで使ってるJostというフォントはこの問題に引っかかるらしく、更に問題が深刻なのは、同じフォントを使ってるhugoのdoksテーマも、この問題にひっかかることです(ここのページのFAQのAの文字がmacでおかしな表示になります)つまりzolaとかadidoksに関係なく起こる問題です。

解決策: JostフォントをRobotoフォントで入れ替える => その後入れ替えない解決策を発見!(追記)

その後入れ替えなしで解決できました!(追記参照)

フォント入れ替えの参考になるかもしれないので、ここの記事は残して起きます。やっぱり考えるのをやめてはだめですね(笑)

どうやらJostやInter等、特定のフォントだけで起こる問題であるらしく、その他のフォントだと何の問題もないようなので、Jostを人畜無害そうなRobotoに入れ替えるという、やっつけ感満載の方法で解決します。

adidoksのフォント設定は sass/common/_fonts.scss で確認できます。これに対応しそうなrobotoフォントを次のサイトからダウンロードします。

google webfonts helper
A Hassle-Free Way to Self-Host Google Fonts. Get eot, ttf, svg, woff and woff2 files + CSS snippets!

ダウンロードしたフォントはstatic/fonts/vender/roboto 内に配置。それに対応するようにsass/common/_fonts.scss内のバス指定を書き換えます。

これだけだとsass内のJostフォント指定が残ってしまいます。つまりsassがJostだと思って処理してるフォントが、実際はrobotoであるという不憫な状態なのですが、もうこれ以上深入りしたくない私は、考えるのをやめました(笑)

まとめ

ツールはユーザー数・開発アクティビティーが大切?

hugoのdoksをzolaに移植してくれたadidoksの作者様には感謝しかありません。ただソースを見る限り、どうもJSON-LDあたりで力尽きられたような感じを受けます。githubの活動も当初は盛況だったのですが、その後が続かなかった印象です。誰かがフォークして勝手に引き継げよ、ということなのかもしれません。

先に書いたとおり、adidoksにはJSON-LDの生成にバグがあります。ユーザーが多いとこういう問題はすぐにあぶり出されて、開発が活発ならすぐ修正されるはずです。ユーザーが少ない場合、利用者本人が対応しなければならない部分が大きくなります。adidoksは私のような初心者向けのツールではなかったかもしれません。

そういうことならzolaよりhugoだと言われそうで、実際そうかもしれないのですが、hugoはhugoでmarkup.goldmark.renderer.unsafeをtrueにするのはお約束だ、みたいな理不尽なルールがあったりします(それなら最初っからそうしといてよと思った)hugoが嫌なら後発でよりスッキリしてるはずのzolaに走るのは一つの手です。もちろん、多少の苦労が必要になりますが。

今後の予定

今回の活動で、今使ってるwordpressに加え新たなcmsが稼働し、英語と日本語で同時に情報発信できるシステムが整いました。まだほとんど記事がありませんが、今後順次情報を増やしていく予定です。ドキュメントと同時にブログも書けるシステムになっているので、そのうちwordpressからzolaに全面移行するかもしれません。まあ、そんなことより、てっとりばやくでっち上げた感がみえみえの、本サイトのトップページをまともなページに入れ替えることが先決かもしれません。

今後のtodoとしては

  • フォントを出来ればJostに戻したい(JostのWの尖り具合を見てしまうとrobotoでは物足らない?)=> 追記で解決しました!
  • 殺風景なセクションページを改善したい。アイキャッチ画像が見えるようにする?
  • shortcodeを開発して、ページの作成を加速したい(zolaにもshortcodeのシステムがあります)

でしょうか。

いろいろ弄り回した(じゃなくて強制的に回らせられた?)おかげで、zolaのtemplateシステム(teraというらしい)にだいぶ慣れてしまいました。なんかsassとかbootstrapとか言わなければ、簡単なテーマを自分でつくれちゃうんじゃないかと思ったりもします。emacsのorg-modeが使えるらしいhugoにはだいぶ後ろ髪を引かれる思いがあるのですが、もうだいぶzolaに時間を投資してしまったので、yagifulは今後もzolaで突っ走ります。

追記: 「macでフォントの表示がおかしくなる」をmain.scssを書き換えて解決

私のやっつけ仕事よりはるかにまともな解決策が用意してありました。

Jost font displays incorrectly on macOS · Issue #45 · aaranxu/adidoks
The font included with this theme contains an uppercase "A" character that does not display correctly on all operating s...

sass/main.scssを書き換えます。

@import "common/fonts"; 

の行を次に入れ替えます。

@import url('https://fonts.googleapis.com/css2?family=Jost:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap');  

これでJostで表示されるはずです。

コメント

タイトルとURLをコピーしました