DigiPress

Highly Flexible WordPress Theme

メニュー

Gutenbergから可能になったJavaScript内のテキストを翻訳して表示する新しい方法

2018/12/12

WordPressのテーマやプラグインで、翻訳ファイル(*.mo)を含めて多言語表示に対応させる場合、PHPであれば load_theme_textdomain (テーマの場合)、 load_plugin_textdomain (プラグインの場合) といった関数で キー名と翻訳ファイルのパスを指定すれば、WordPressで設定されているロケールに合わせて表示言語を簡単に差し替えれます。

おさらい : PHP側で多言語対応する場合の例

翻訳ファイルは、POT (Portable Object Template, または PO) ファイルと MO (Machine Object) ファイルがあり、人が編集するのは POTファイルですが、実際に WordPress が翻訳データとして利用するのは、Poedit などを介して POTファイルをバイナリデータに変換した MOファイルです。

例えば日本語化翻訳ファイル(my-textdomain-ja.pot, my-textdomain-ja.mo)があるとして、「languages」フォルダに格納してある環境を想定してみましょう。

POTファイルの定義例

#: theme-name.php:123
msgid "Hello World!"
msgstr "ハロー・ワールド!"

プラグインの場合は、以下のようにします。

add_action( 'plugins_loaded', 'my_load_textdomain' );
function my_load_textdomain() {
    load_plugin_textdomain( 'my-textdomaiin', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
}

テーマの場合はこちら。

add_action( 'after_setup_theme', 'my_load_textdomain' );
function my_load_textdomain() {
    load_theme_textdomain( 'my-textdomain', get_template_directory() . '/languages' );
}

これで、翻訳したいテキストは

__( 'Hello World!', 'my-textdomain' )

などとコーディングしておくと、’Hello World!‘ が翻訳対象となり、翻訳が定義されていれば翻訳表示されます。

WordPress で読み込む JavaScript 内のテキストを翻訳するには?

WordPress で JavaScript から出力させる必要があるメッセージや要素のテキストなどは、サーバーサイトで処理される PHP とは異なりクライアント(端末)側で実行されるため、従来の方法では wp_localize_script 関数を用いて翻訳対象の Javascript ファイルのハンドル名を登録し、Javascript 側では wp_localize_script 関数の第二引数に指定した名前空間を一致させて、wp_localize_script 関数でローカライズされたテキストを渡すという、ちょっとまわりくどいやり方が定番でした。

wp_localize_script の場合(PHP)

wp_localize_script(
	'my-custom-js',	// 翻訳対象のテキストを含むJavascriptファイルのハンドル名
	'my_localize_text',	// Javascriptで指定する翻訳箇所の変数名
	array(	// 翻訳テキストのキー名と表示テキストの配列をまとめておく
		'hello_world' => __( 'Hello World!', 'my-textdomain' ),
		'settings_updated' => __( 'Settings updated', 'my-textdomain' ),
	)
);

wp_localize_script の場合(JS)

alert( my_localize_text.hello_world );

この方法は、翻訳対象のテキストが増えるほど JavaScript ファイルの冗長化を招き、メンテナンス性もこの上なく悪くなり気持ち悪いコードがどんどん増殖します。

ところが、WordPress 5.0から標準エディターとなる Gutenberg の登場で、i18n npm モジュールが新たに利用可能となり、JavaScript 側でも PHP の場合と全く同じ書式のみで翻訳が可能となりました!

Gutenbergのブロック開発では、ほぼ JavaScript(React.js + ESNext)で行うため、多言語対応にするには以下のようにします。

WordPress i18n モジュールのインストール

前置きがながくなりましたが、ここからが本題
ターミナルから以下のコマンドを実行して WordPress の i18 モジュールを対象ディレクトリにインストールしておきます。

npm, Webpack, Babel 等のインストール、セットアップが一通り完了している前提。
npm install --save @wordpress/i18n

ローカリゼーション関数を使用可能にする (JS)

JavaScript 側で、i18n モジュールからローカリゼーション関数が使用可能となるようインポートします。

import { __, _n, sprintf } from '@wordpress/i18n';

これで、Javascript内の翻訳したいテキスト部分はすべて

{ __( 'Hello Gutenberg!', 'my-textdomain' ) }

などとしておきます。

POT(PO)ファイルからJSON形式の翻訳ファイルに変換

WordPress 5.0 からは、これまでの翻訳ファイル(.mo)ではなく、元の POファイルから JED形式の JSON 形式に変換した翻訳ファイルを用意する必要があります。

POファイルからJSONに変換するには、po2jsonなどのライブラリを利用します。

po2json のインストール

npm コマンドで、po2json パッケージをインストールします。

npm install po2json
JED 形式で POT(PO)ファイルから JSON ファイルに変換

翻訳ファイル(.json)は 「テキストドメイン名」-「ロケール」-「ハンドル名」.json というファイル名にする必要があります。

po2json languages/my-textdomain-ja.po languages/my-textdomain-ja-my-gutenberg-blocks-editor.json -f jed

JavaScript で翻訳ファイルを読み込む (PHP)

enqueue_block_editor_assets フックを介して、翻訳データを指定したハンドル名の JavaScript ファイルに渡します。

WordPress 5.0 からは、wp_set_script_translations という関数で、対象の JavaScript ファイルのハンドル名とテキストドメイン名を引数に指定するだけで翻訳されるようになりました。

プラグインの場合の例

add_action( 'enqueue_block_editor_assets' , 'my_editor_assets' );
public static function my_editor_assets() {

	// 翻訳化したいテキストを含むGutenbergブロックのスクリプト
	wp_enqueue_script(
		'my-gutenberg-blocks-editor', // ハンドル名
		plugins_url( 'js/editor.build.js', __FILE__ ), // 読み込むスクリプト
		array( 'wp-blocks', 'wp-element', 'wp-i18n' ), // 依存するスクリプト(先にロードすべきもの)
		filemtime( plugin_dir_path( __FILE__ ) . 'js/editor.build.js' ), // バージョン指定(キャッシュ対応)
		true	// body終了前にロード
	);

	if (function_exists('wp_set_script_translations')) {
		// WordPress 5.0 以降
		wp_set_script_translations( 'my-gutenberg-blocks-editor', 'my-textdomain', plugin_dir_path( __FILE__ ) . 'languages' );

	} else if (function_exists('gutenberg_get_jed_locale_data')) {
		// WordPress 4.9.8 以下(Gutenberg プラグインの場合)

		// load_textdomain に指定したドメイン名を指定
		$locale  = gutenberg_get_jed_locale_data( 'my-textdomain' );

		// 翻訳データを Javascriptオブジェクト(setLocaleData)に追加
		$content = 'wp.i18n.setLocaleData(' . json_encode( $locale ) . ', "my-textdomain" );';

		// 指定したハンドル名のJavascriptの前にインラインで翻訳データ(JS)を挿入
		wp_script_add_data( 'my-gutenberg-blocks-editor', 'data', $content );
	}
}

これで、冗長化していく wp_localize_script 関数を使用しなくても PHP と同じように JavaScript 内のテキストも翻訳されます。

参考

https://wordpress.org/gutenberg/handbook/designers-developers/developers/internationalization/
https://make.wordpress.org/core/2018/11/09/new-javascript-i18n-support-in-wordpress/
https://github.com/ampproject/amp-wp/pull/1634

Share / Subscribe
Facebook Likes
Tweets
Hatena Bookmarks
Pinterest
Pocket
Feedly
Send to LINE