Before Gutenberg – JavaScript多言語化の新しい形

Gutenbergはそのソースの多くがJavaScriptから構成されている。そこで問題となるのが多言語対応(Internationalizationを略してi18nなどと書く)なのだが、これまでは次のようにやや迂遠な方法を使っていた。

// PHP
wp_enqueue_scripts( 'my-script' );
wp_localize_script( 'my-script', 'MyScript', [
    'title'             => __( 'My Script', 'my-domain' ),
    'description' => __( 'This is my script.', 'my-domain' ),
] );

//JS
alert( MyScript.title );

要するに、これまではPHPで翻訳した文字列を定義し、それをwp_localize_script関数でパスしていたわけだ。

この方法のダルいところは、JavaScriptを書いている最中に、わざわざPHPファイルを開かなければならないところである。いったりきたりしているうちに、「あれ、なにしようとしてたんだっけ?」と記憶喪失になってしまい、twitterやfacebookで時間を潰し始め、気づいたら2時間ぐらい経っていたという事態がよく発生する。

こうした問題点(?)を解消すべく、GutenbergおよびWordPress 5.0ではJavaScriptに直接翻訳関数を書くことができる。いまのところ、GutenbergとWordPress 5.0ではちょっとやり方が異なるのだが、基本的にはPHPで利用していたのと同じドメイン指定でできる形に変わった。

// JS読み込み時に、wp-i18nを依存関係に追加する。
wp_enqueue_script( 'my-script', $url, [ 'wp-i18n', 'jquery' ], $version, true );
// Gutenbergのちょっと古いやり方
if ( function_exists( 'gutenberg_get_jed_locale_data' ) ) {
	$json = json_encode( gutenberg_get_jed_locale_data( 'my-domain' ) );
	wp_add_inline_script(
		'my-script',
		sprintf( 'wp.i18n.setLocaleData(  %s, "my-domain" );', $json ),
		'before'
	);
}
// WordPress 5.0
if ( function_exists( 'wp_set_script_translations' ) ) {
	wp_set_script_translations( 'my-script', 'my-domain' );
}

このように書いておくと、JavaScript内で見慣れた___xといった翻訳関数が使えるようになる。

// 関数を読み込み
const { __ } = wp.i18n;

alert( __( 'My Script', 'my-domain' ) );

これでPHPとJSを行ったり来たりすることによる記憶喪失も防げるだろう。

追記・翻訳用JSONを作成する必要がある?

※2020年1月9日さらに追記 WordPress 5.3ぐらいからGlotPress(WordPressの翻訳プラットフォーム)がJSの解析にも対応したようで、少なくとも公式リポジトリで配布する場合は翻訳用のJSONを書き出す必要は無くなった。よって、以下のパートはすでに無効になった情報も幾分含んでいる。(タレコミはCapital P会員の大橋直記さん)

さて、この記事を公開後、WordPress 5.0がリリースされたが、SnowMonkeyの北島氏よりツッコミが入った。

筆者も自身でリリースしたWP-YomiganaをWordPress 5.0に対応したところ、翻訳が聞いていないことが判明。公式ブログのリリース確認したところ、以下のようなことがわかった。

  • wp-i18nスクリプトを依存関係に読み込めば、moファイルの翻訳が適用される(ように筆者は読めた)
  • しかし、上記のような状態は確認されていない。”in upcoming weeks”とのことなので、まだリリースされていないのだろう。

Translation and Language packs support for plugins and themes that are hosted on the repo is expected in the upcoming weeks. The patches are ready and waiting for commit.

要するに、上記で紹介した方法ではまだ翻訳されないようだ。GlotPress経由でも翻訳が変更された印象はない。よって、Advanced Usageとして紹介される情報によると翻訳用のJSONを作成し、それを指定することで翻訳が適用される。

また、上記で紹介した方法は「WordPress.orgで公開されるプラグイン・テーマ」に限る。したがって、自分で販売しているテーマやプラグインは別の方法を取る必要がある。

ステップ1. 翻訳用JSONを作成する

さて、これまでになかった処理として、poファイルから翻訳用JSONを生成しなければならない。これにはnpmパッケージを利用する。

npm install po2json

このコマンドをnpmスクリプトなどに追加して、翻訳対象のpoファイルを指定すると、JSONが生成される。JSONの命名規則は{$domain}-{$locale}-{$handle}.jsonとなる。

po2json languages/wp-yomigana-ja.po languages/wp-yomigana-ja-definition-list.json -f jed

ステップ2. 翻訳を読み込む

続いて、wp_enqueue_scriptで読み込む時に、wp_set_script_translationsを実行する。ハンドルごとに実行することを忘れないように。引数の順番はハンドル名、ドメイン、翻訳ファイルのディレクトリ。

wp_register_script( 'wp-yomigana-dl', $this->assets . '/js/dist/definition-list.js', [ 'wp-i18n' ], '1.0.0', true );
wp_set_script_translations( 'wp-yomigana-dl', 'wp-yomigana', plugin_dir_path(  __DIR__  ) ) . 'languages' );

これで無事翻訳が適用された。

雑感

さて、実際にやってみて、問題がありそうだなと思ったのは下記の点だ。

  • この方法だと、翻訳対象言語と同じ数だけJSONを生成しなければならない。が、自作テーマなどでは2,3ヶ国語に対応していれば済むので、問題はないか。
  • 翻訳を新たに追加する方法がよくわからない。筆者はWooCommerceなどのプラグインを購入し、後から翻訳ファイルを追加するということをやっているので、その場合どうしたものだろう。
  • PHPとJSで翻訳ファイルをわけるのがめんどくさすぎるので、WordPress.orgの翻訳機能がリリースされればありがたいことことの上ないのだが、いつになるのだろうか。

おまけ 翻訳対象のスクレイピング

さて、テーマやプラグインを作っている方は、翻訳対象となる文字列をpotファイルなどに書き出していることだろう。おそらく、WordPressの公式翻訳プラットフォームであるGlotPressを使えば悩むことはないだろうが、自作テーマや販売用テーマなどを使っている方は、potファイルを作成する方法がこれまでとは変わることになる。いままではPHPファイルだけをスクレイピングすればよかったのだが、今度はJSが追加されるからだ。

方法1 WP-CLI

WordCamp Tokyo 2018にもきていたPascal Birchlerが勧めるように、WP-CLIのパッケージコマンドを追加することで、翻訳対象をいい感じに抽出できる。

package install wp-cli/i18n-command
wp i18n make-pot

npmスクリプトと組み合わせれば、自動で書き出すこともできるだろう。

方法2 PoEdit

PoEditは古くからあるGUIの翻訳カタログエディタである。こちらではデフォルトでJSが無視されるので、まずは「カタログ > 設定 > ソースのパス」にある無視リストからJS *.js を外そう。

続いて、これはgettext業界ではわりと知られたハックらしいのだが、翻訳対象の抽出としてJavaScriptは入っていないので、表記が似ているPythonを採用するようだ。「設定 > 抽出ツール」を選んでPythonを編集し、次のような設定にする。

Pytonの設定部分を書き換えるとJSも有効になる。

これで今まで通りのワークフローが使えるはずだ。

以上、プラグインやテーマ作者の頭を悩ませていたJavaScriptの翻訳めんどくさい問題が片付いたので、WordPress 5.0からは気軽にJSに文字列を書くことができるだろう。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください