多言語サイトの簡単な作り方まとめ a-blog cms 2023

a-blog cms は多言語サイトをよく作る制作者には特にオススメです。このエントリーでは特に、標準機能だけを使う(たぶん最も)簡単な多言語サイトの作り方をご説明します。

a-blog cms の基礎を理解していればすぐに使える内容なので、はじめて多言語サイトを作る方、多言語サイトを作ったことはあるけれど他のやり方も知りたい、という方はぜひ参考にしてみてください。

このエントリーでは説明を簡略化するために日本語をベースとする日英2言語のサイトを想定していますが、実装方法とソースは3ヶ国語以上の場合でも対応できるように意識しています。

  • ルールやテーマは言語の分岐以外、たとえばスマートフォン/PCの分岐、子ブログごとの分岐にも使われるため、言語の分岐にも使うとサイトの構造が複雑になりがちなのでこのエントリーでは扱いません。
  • 数カ国語を扱う大規模サイトなどには、有償の拡張アプリの使用にも検討すべきメリットがあります。

エイリアスで多言語サイトを分ける

まずは言語ごとのエイリアスを用意します。管理画面 > エイリアス で [エイリアスの作成] をクリックします。

  • 名前には「_en」のように言語ごとのコードネーム(URLに使われる文字列)の前にアンダースコアを足したものを入力します。(%{ALIAS_NAME} をカスタムフィールドやモジュールIDの接尾辞としてそのまま使えるようになります)
  • サイト全体を多言語化する場合にはルートブログでエイリアスを作って「グローバル」にチェックを入れます。特定のブログだけを多言語化する場合はそのブログにエイリアスを作ります。

英語用エイリアスの作成例

これですでに英語エイリアスサイトでベースの日本語と同じ内容が表示されていることになります。この後、

  • テンプレート
  • 文字列
  • カスタムフィールド
  • モジュールID
  • ユニット

を言語によって出し分けていきます。

テンプレートはinclude文 と %{ALIAS_CODE} で出し分ける

a-blog cms は 3系から テンプレートキャッシュ がオンの状態がデフォルトになって高速化されています。テンプレートキャッシュがオンの状態では include文に使える ALIAS 関連のグローバル変数は %{ALIAS_CODE} のみになります。なので、%{ALIAS_CODE} を使ってテンプレートをファイルごと、あるいはフォルダごとに出し分けます。

  • テンプレートキャッシュをオフの状態にするのであれば他のグローバル変数を使っても良いのですが、新規制作のサイトは特に、テンプレートキャッシュはオンで使うのがオススメです。
  • テンプレートキャッシュがオンの状態を意識しておくことで案件をまたいでソースを活用しやすくなります。

%{ALIAS_CODE} は上記のような設定の場合、ベースの日本語では空で、英語は enとなっています。なので、インクルード元のファイルには

@include("/include/file-name_%{ALIAS_CODE}.html") <!-- ファイルごとの分岐 -->

のように書いて、インクルード先のファイルとして

  • /include/file-name_.html (日本語)
  • /include/file-name_en.html (英語)

を作成します。フォルダごとの分岐も同じ考え方で作ります。日本語のファイル名やフォルダ名がアンダースコアで終わっているのがすこし落ち着かない感じがするかもしれませんが、慣れてしまえば「分岐がある場合のベース言語」のファイルあるいはフォルダであるという目印にもなります。

文字列の出し分けは SetTemplate を使って訳語をまとめておく

テンプレートを分けるほどではない、文字列の出し分けは次のようにすると簡単です。

  1. ひとつのファイルに SetTemplate を使って訳語をまとめておく
  2. 訳語を出し分けたいファイルの冒頭で1のファイルを include する
  3. GET_Template で表示する

たとえばテーマに /translation/string.html というファイルを用意して、次のように記述します。

<!-- BEGIN_SetTemplate id="1" -->
<!-- 静的な文字列の例です -->
<!-- BEGIN_IF [%{ALIAS_CODE}/eq/en] -->Privacy policy
<!-- ELSE -->プライバシーポリシー
<!-- END_IF -->
<!-- END_SetTemplate -->

<!-- BEGIN_SetTemplate id="date" -->
<!-- エントリー系モジュールのentry:loop の内側で使えます -->
<!-- BEGIN_IF [%{ALIAS_CODE}/eq/en] -->{date#F} {date#j}, {date#Y}
<!-- ELSE -->{date#Y}年{date#n}月{date#j}日
<!-- END_IF -->
<!-- END_SetTemplate -->

このファイルを使いたいテンプレートファイルの冒頭に include します。すべてのテンプレートファイルに include したい場合は、base.html の body-start セクションに include すると良いでしょう。

@section("body-start")
@include("/include/body_start.html")
@include("/translation/string.html")
@endsection

これで、下記のように記述すれば表示できます。trim="1" を追加しておけば余計な改行が削除されてきれいなソースになります。

<!-- GET_Template id="1" trim="1" -->
<!-- GET_Template id="date" trim="1" -->

dateのように特によく使う文字列以外は、番号だけをidにしておくのがオススメです。長い文章の場合などにも迷わずidを振れてコーディングのスピードが上がりますし、訳語の id は使いたいときに検索すればすぐに分かるからです。言語の分岐を実装する段階でスプレッドシートなどに訳語がまとまっていれば、idの番号を含め、string.html を簡単に作れます。

SetTemplate の中のテンプレートは解決する前に変数化されていて、GET_Template で呼び出されたものだけが解決されるので訳語が多くなってもパフォーマンスにはさほど影響はありません。

カスタムフィールドは %{ALIAS_NAME} を接尾辞に使って出し分ける

カスタムフィールドは管理画面側では {field_label}、{field_label_en} のように作っておき、表示側では {field_label%{ALIAS_NAME}} と書いて出し分けます。日英でこのフィールドが必須項目の場合はこれだけで良いので簡単です。

しかし、英語のフィールドに入力がない場合は日本語のフィールドの内容を出力したい、というような場合は多いと思います。その場合は、include と組み合わせます。たとえば、テーマに /translation/field.html というファイルを用意して、次のように記述します。

<!-- BEGIN_IF [{{{label}}}/nem] -->
 <p>
  <!-- BEGIN_IF [{{{label}}%{ALIAS_NAME}}/nem] -->
  {{{label}}%{ALIAS_NAME}}
  <!-- ELSE -->
  {{{label}}}
  <!-- END_IF -->
 </p> 
<!-- END_IF -->

まず日本語のフィールドに入力がない場合は何も出力しないように全体を IF で囲み、その内側で現在のエイリアスの言語用のフィールドに入力があるかないかで分岐しています。

表示したい箇所での include文の書き方は以下のとおりです。

@include("/translation/field.html", {"label":"field_label"})

field.html というファイルはひとつだけ用意すればよく、include文で label 変数を渡して表示するという仕組みです。{title} も {title_en} というカスタムフィールドを用意し、

@include("/translation/field.html", {"label":"title"})

と書くことでこの条件で出し分けができます。もちろん、{title_en} が必須項目の場合は、{title%{ALIAS_NAME}} と書くだけでオーケーです。

モジュールIDも %{ALIAS_NAME} を接尾辞に使って出し分ける

テンプレート側では id="nav_global%{ALIAS_NAME}" と指定しておき、管理画面側では nav_global、nav_global_en とそれぞれの言語用のモジュールIDを作成することによって、モジュールIDも簡単に出し分けることができます。ナビゲーションモジュールの文言をそれぞれの言語に対応させたり、title_en に入力があることをエントリーサマリーモジュールの条件にしたりなど、いろいろなカスタマイズが考えられます。

ユニットを多言語化する

a-blog cms なら、ユニットの種類によって多言語化したり共通化したりするカスタマイズも簡単です。そのやり方をご説明します。


テキストユニット、メディアユニット、テーブルユニットを多言語化した管理画面

管理画面側のテンプレート

まず /themes/system/admin/entry/unit_language.html を使用しているテーマの同階層に複製し、unit.html とリネームします。

開いてみると分かるとおり、このファイルは /admin/entry/_layouts/admin-unit.html を継承し、多言語化したいユニットのセクションの中味を書き換えてあります。多言語化せず、全言語共通で使いたいユニットや、そもそも使用しないユニットについては、セクションごと削除してください。

エントリーの編集画面では、各ユニットに 日本語 / English のタブができているのが確認できます。

表示画面側のテンプレート

まず /themes/system/include/unit.html を使用しているテーマの同階層に複製します。

開いてみると分かるとおり、このファイルは /_layouts/unit.html を継承しているだけです。これも、通常のテンプレートと同様、include と %{ALIAS_CODE} を使って出し分けていきます。

まず、unit.html は次の1行だけに書き換えます。

@include("/translation/unit_%{ALIAS_CODE}.html")
  • /translation/unit_.html
  • /translation/unit_en.html

を作成します。

日本語用のファイルはユニットをそのまま出すだけなので(他にユニットのカスタマイズがなければ)次の1行だけにして /_layouts/unit.html を継承します。

@extends("/_layouts/unit.html")

英語用のファイルには日本語と同じく @extends("/_layouts/unit.html") を1行目に書いたあと、多言語化したいユニットのセクションだけを継承元のファイルからコピペしてきて、英語用の入力を出力するように書き換えます。たとえばテキストユニットを多言語化する場合は {text} を {text2} に置換して、こうなります。

@extends("/_layouts/unit.html")

@section(text-unit)
<!-- テキスト -->
<!-- BEGIN p -->
<p{class}>{text2}[raw|nl2br]</p><!-- END p --><!-- BEGIN h2 -->
<h2{class} <!-- BEGIN_IF [{extend_tag2}/nem] -->id="{extend_tag2}"<!-- END_IF -->>{text2}[raw|nl2br]</h2><!-- END h2 --><!-- BEGIN h3 -->
<h3{class} <!-- BEGIN_IF [{extend_tag2}/nem] -->id="{extend_tag2}"<!-- END_IF -->>{text2}[raw|nl2br]</h3><!-- END h3 --><!-- BEGIN h4 -->
<h4{class} <!-- BEGIN_IF [{extend_tag2}/nem] -->id="{extend_tag2}"<!-- END_IF -->>{text2}[raw|nl2br]</h4><!-- END h4 --><!-- BEGIN h5 -->
<h5{class} <!-- BEGIN_IF [{extend_tag2}/nem] -->id="{extend_tag2}"<!-- END_IF -->>{text2}[raw|nl2br]</h5><!-- END h5 --><!-- BEGIN ul -->
<ul{class}>{text2}[raw|list]</ul><!-- END ul --><!-- BEGIN ol -->
<ol{class}>{text2}[raw|list]</ol><!-- END ol --><!-- BEGIN dl -->
<dl{class}>{text2}[raw|definition_list]</dl><!-- END dl --><!-- BEGIN blockquote -->
<div class="entry-container">
<blockquote{class}>{text2}[raw|nl2br]</blockquote>
</div><!-- END blockquote --><!-- BEGIN table -->
<div class="entry-container">
<table{class}>{text2}[raw|table]</table>
</div><!-- END table --><!-- BEGIN pre -->
<div class="entry-container">
<pre{class}>{text2}</pre>
</div><!-- END pre --><!-- BEGIN none -->
{text2}[raw]<!-- END none --><!-- BEGIN markdown -->
{text2}[raw|markdown]<!-- END markdown --><!-- BEGIN wysiwyg -->
{text2}[raw]<!-- END wysiwyg -->

@include("/include/unit/tag-select.html")
@endsection

他のユニットも、多言語化したいセクションをコピペしてきて必要な箇所を書き換えます。ポイントは、

  • 管理画面のテンプレートと表示画面側のテンプレートで多言語化するユニットの種類が一致していること
  • {text} -> {text2} のように言語別に入力できる欄を言語別に出力するように置換すること

のふたつです。テキストユニットとメディアユニットだけというような単純なサイトなら、ユニットの多言語化も簡単ですね。言語の種類が多くなっても、include を使った分岐なのでテンプレートは複雑化せず、ただ言語の種類分のファイルが必要になるだけです。

まとめ

以上、a-blog cms の2023年3月時点での最新バージョンに合わせた、効率的で簡単な多言語サイトの作り方をまとめてみました。WordPress では多言語サイトは有料サブスクリプションのプラグインを使うことが前提になりますが、a-blog cms なら買い切りのライセンス料だけでも使いやすい多言語サイトを効率的に作れます。多言語サイトのCMS選定の候補にぜひ a-blog cms を入れてみてください。

おまけ:言語スイッチャーは JavaScript で作る

ブログトップ、カテゴリートップ、エントリー詳細などそれぞれのページから、他の言語の対応するページへリンクする言語スイッチャーは、JavaScript で作るのが簡単です。それぞれの言語の対応URLの違う部分が言語のスラッグ(/en, /zh, /ko など)だけである場合は、a-blog cms で構築したサイトに限らず、静的なサイトや他の CMS のサイトでも使える言語スイッチャーを作ってみました。これに関しては、こちらでエントリーを分けてご紹介しています。


この記事をシェアする

この記事を書いた人

有限会社 アップルップル

admin

このブログでは a-blog cms の実装に関することを中心に、CSS、JavaScriptなどフロントエンド周辺のことを書いていきます。

おすすめ記事

この記事のハッシュタグ から関連する記事を表示しています。

タグ一覧