【Jekyll + jQuery】特定の記事でのみ動作する言語切り替えボタンの実装

追記(2021/8/28)

ジェネレータをJekyllからHugoに変更したので言語切り替えボタンを一次的に削除しました。

あらすじ

Google Analysis見る感じSingapole, China, U.S.A. 辺りからちょくちょくアクセスがあるので、それに合わせて前々から実装したいと思っていた記事の言語切り替えボタンをjQueryで実装しました。

ただ、今までjQueryはおろかJavaScripをほぼ扱ったことが無かった上に、検索しても言語切り替えについての具体的な方法が出てこなかったので参考になれば良いなと思って残しておきます。

おおまかな仕様

  1. 日本語・英語切り替えボタンを特定の記事だけに表示
  2. 翻訳についてはGoogle Translate、DeepLなどに投げても良かったが、せっかくなのでライティングの練習がてら自力で翻訳(つまり英語記事用に別ファイルを用意する)。
  3. Jekyllのコレクション機能を使ってホーム画面の「最近の投稿」などの投稿記事一覧上に英語の記事を出さない
  4. 「最近の投稿」一覧上で、英語の記事が用意してある日本語記事には"English article availabe"と表示
  5. 英語の記事のURLを日本語記事のURL/enとする

最近の記事一覧を表示するセクションでは↓みたいな表記にしたいと思って進めていました。

package

ボタンの実装

ボタンのデザインは以下のサイトの物をお借りしています。

See the Pen How to show buttons for changing lang. on pages powered by Jekyll by htnabe (@htnabe) on CodePen.

HTMLとCSSを多少書き換えれば凝ったデザインのボタンも作れると思います。

JSについて、特にボタンの扱い方については他にも方法があると思います。皆さんのボタンの配置場所やお望みの動作を鑑みてコードを書き換えてください。

今回特にハマった部分ですが、jQueryでは$(document).ready(function(){})$(window).bind("load" function(){})の意味合いは大きく異なります。

前者はDOMが構築された後に実行される関数を定義でき、後者では使用される素材(画像、ボタン、その他要素)が完全に読み込まれた後に実行される関数を定義できます。DOMについては↓を参照してくだあしあ。

特に今回$(window).bind("load" function(){})内に記した処理は「URLに"/en"が含まれていたらENG buttonをcheckedにする」というものですが、この処理については$(document).ready(function(){})内に記しても動きませんのでご注意ください。

言語切り替えボタンの出現条件の設定

今回ja_enというパラメータを用意し、日本語記事とそれに対応する英語記事にja_en: trueとした場合のみ言語切り替えボタンが出現するという仕様にしています。

この処理については実装が簡単で、本サイトのジェネレータであるJekyllでは_config.yml内や各記事のフロントマター内でja_enといったパラメータをユーザー側で定義することで容易に値を参照・変更できるようになっています

例えばja_enを本記事のフロントマターに埋め込むと次のようになります。

title: 【Jekyll + jQuery】特定の記事でのみ動作する言語切り替えボタンの実装
tag:
  - Jekyll
  - jQuery
  - Changing Language
categories: Tech
show_date: true
ja_en: true
excerpt: 特定の記事のみで動作する言語切り替えボタンをjQueryで実装しました。

これを用いて、ja_en: trueの場合のみボタンを出現させようと思うと先ほどのCODEPENで示したhtmlファイルの内容を少し書き換える必要があります。例えば下の様になります(これをpage__meta-ja_en.htmlとします)。

{% assign document = post | default: page %}
{% if document.ja_en %}
    <span class="page__meta-changelang">
    文<i class="fas fa-fw fa-exchange-alt" aria-hidden="true"></i>A
  	<input type="radio" name="switch" id="radio1" checked>
  	<label for="radio1">JAN</label>
  	<input type="radio" name="switch" id="radio2">
  	<label for="radio2">ENG</label>
    </span>
{% endif %}
</code>
</pre>

こうすることでja_en: trueの場合のみボタンを出現させることが出来ます。

最近の記事一覧上では「English article availabe」と表示

これについてもja_enパラメータを用います。

方法は

  1. 英語記事と対になる日本語記事のフロントマターにもja_en: trueを記す
  2. 「最近の記事」一覧ページに関わるhtml上にて、記事のja_enがtrueの時のみEnglish article availableを表示

ってだけです。これはめちゃくちゃ簡単で、単に先ほどのpage__meta-ja_en.htmlのJAN <=> ENGの切り替えボタン部分を書き換えるだけで実装可能です(これをpage__meta.htmlとします)。

<!--page__meta.html-->
{% highlight html linenos %}{% raw %}
{% assign document = post | default: page %}
{% if document.ja_en %}
    <span class="page__meta-changelang">
        文 <i class="fas fa-fw fa-exchange-alt" aria-hidden="true"></i> A: English article available
    </span>
{% endif %}

例えば、今紹介した2つのhtmlファイルを使って

  1. page_meta-ja_en.htmlを作成して記事上では切り替えボタンを表示
  2. 記事内容を表示するためのpost.html(仮名)内でpage__meta.htmlをインクルード
  3. page__meta.htmlを作成し記事一覧上ではEnglish article availableを表示
  4. 記事一覧を表示するためのarchive.html(仮名)内でpage__meta.htmlをインクルード

等としてあげると問題なく表示できると思います。

Jekyllのコレクション機能を使った英語記事の隔離

英語の記事を最近の記事一覧上に表示させると日本語の記事と入り乱れて大変だと思ったので、Jekyllのコレクション機能を使って英語記事を日本語記事(/_posts)とは別のフォルダで管理することとしました。

下のサイトの内容などを参照しました。

自分はホームページのroot直下に/eng-postsというフォルダを作成し、回答の通り_config.tml内で

collections:
  eng-posts:
    output: true

としました。これにより、eng-postsフォルダ内に配置したマークダウンファイルを外部のファイルからも読み込めるようになります。

ちなみに、bundle exec jekyll serve --profileコマンドでeng-posts内のファイルのビルドを確認しましたが普通に/_posts内の記事同様特にビルドされており、ビルド時間が極端に遅くなることはないようです。

そして最後に英語記事用URLの設定ですが、様々なサイトで用いられている日本語記事のURL/enの形を踏襲しています。単にpermalink: /tech/changeLangJektll/enといった形で記事のフロントマターに追加すれば所望のURLで確認できます。

One comment ... 実装してみて気付いたけど全記事に対応させようと思うと大変だし翻訳webサービスって偉大なんやなって