WordPressのプラグインやテーマを作っていて、最新に追加したテキスト部分のみ多国語化がされないという症状が発生してちょっとハマったので、解決方法を備忘録として残しておく。
はじめに確認しておくべき項目
まず、WordPressにおいて一部だけ多国語化が反映されないというケースで、一般的な確認項目は下記の通りだ。
- 言語バイナリファイル
*.mo
ファイルの不備
──例えば、*.po
ファイルは更新したが、*.mo
ファイルを書き出していなかったり、更新していなかったりというケースだ。生成時にエラーが発生して、正常な*.mo
ファイルが作られていない等のケースもありえる。この場合、翻訳処理のデータ実体であるバイナリファイルのみ古くなっていて、最新の翻訳のみが反映できない状態なので、最新の*.mo
ファイルを生成してあげれば解決する。 -
追加テキスト部にテキストドメイン名が指定されてない
──この場合、追加したテキスト部のソースが__( 'new added text' )
のようになっていて、本来あるべきテキストドメイン名がないことが原因だ。本来なら__( 'new added text', TEXT_DOMAIN )
というようにテキストドメイン名を指定する必要があり、テキストドメイン名が指定されないと、WordPressコアの翻訳ファイルからマッチする文字列を探して翻訳が行われる。この際、WordPressコアに「new added text」という翻訳キーが定義されていないと翻訳は行われない。解決方法はもちろんテキストドメイン名をしっかり関数の第二引数に指定してあげればよい。 -
プラグインやテーマ側での多国語化関数の使用不備
──プラグインであれば load_plugin_textdomain、テーマであれば load_theme_textdomain の関数の利用に間違いがあるケースだ。そもそも関数がなかったり、ソースの更新時に削除してしまったりしていないかを確認する必要がある。あとは、関数の使い方が正しいかも確認しておく必要がある。 -
翻訳ファイルの不備
──こちらは、翻訳ファイルである*.mo
ファイルのファイル名や配置場所に問題がある場合だ。翻訳ファイルは{プラグイン名/テーマ名}-{言語コード}.mo
となっている必要があり、例えばプラグイン「wp-plugin」の日本語用の翻訳ファイルであればwp-plugin-ja.mo
としなければならない。紛らわしいのが、言語コードで、英語だとen_US
のように英語の言語コードen
の後にUS
といったロケールが付くが、日本語はロケール型でja_JP
と指定すると翻訳ファイルとして読み込まれなくなるので注意が必要だ。また、翻訳ファイルの置き場所は先のload_plugin_textdomain
やload_theme_textdomain
で指定したパスに置く必要があり、場所を間違えると翻訳されない。読み込みが正常に行われているかどうかは各関数の戻り値を調べればよく、例えばvar_dump( load_plugin_textdomain( PLUGIN_NAME, false, "{PLUGIN_NAME}/languages" ) );
のようにしてTRUE
が返って来ていれば正常に読み込まれていることになる。
既に多国語化されているプラグインやテーマに翻訳テキストを追加した場合、当てはまるケースは 1. か 2. のどちらかになるハズだ。もしソースのディレクトリ構成や翻訳処理周りを変更しているなら、3. や 4. が疑わしくもある。
だが、私の陥った症状は上記のどれにも合致しなかった…。
翻訳ファイルの読み込み優先度を確認する
結論として、私のプラグインでの翻訳ファイル読み込み処理(下記)がまずかった。
$plugin_name = plugin_basename( plugin_dir_path( __FILE__ ) );
$plugin_lang_dir = $plugin_name . '/langs';
load_plugin_textdomain( $plugin_name )
or load_plugin_textdomain( $plugin_name, false, $plugin_lang_dir );
この処理では、まず翻訳ファイルの格納場所を指定していないload_plugin_textdomain( $plugin_name )
を評価し、その後にload_plugin_textdomain( $plugin_name, false, $plugin_lang_dir )
を評価する仕様だ。前者の評価時にWordPressは‘wp-content/languages/plugins/‘のディレクトリ内を捜査し、そこに翻訳ファイルがなければ、本来のプラグインディレクトリ内の指定パスを探すことになる。
以前(おそらくWordPress4.3の頃)はこれでも問題なく動いていたのだが、WordPress4.4以降(?)になってからなのか、管理画面の「更新」メニューからプラグインやテーマも個別に言語ファイルの更新が行えるようになって、ここで更新が行われた言語ファイルはwp-content/languages/
内にプラグインならplugins/
、テーマならthemes/
のそれぞれのフォルダに格納されるようになった。そうなると、今まで「翻訳ファイルなし」でFALSE
を返していたload_plugin_textdomain( $plugin_name )
がTRUE
を返すようになり、読み込む翻訳ファイルが意図しないものになってしまったのだ。
まぁ、原因さえわかってしまえば対処方法は簡単で、読み込ませたくないwp-content/languages/
にある該当の翻訳ファイルを削除してしまえばよい。
ただ、それだけだと根本的な解決にならず、管理画面から「更新」を行ってしまうと、また同じ状況が発生する可能性がある。
──という事で、プラグイン側で翻訳ファイルの読み込み処理を修正しておくのが一番確実である。
$plugin_name = plugin_basename( plugin_dir_path( __FILE__ ) );
$plugin_lang_dir = $plugin_name . '/langs';
load_plugin_textdomain( $plugin_name, false, $plugin_lang_dir )
or load_plugin_textdomain( $plugin_name );
──と、load_plugin_textdomain
関数の評価順を変更しても良いが、特にload_plugin_textdomain( $plugin_name )
を指定しておくメリットはないので、
$plugin_name = plugin_basename( plugin_dir_path( __FILE__ ) );
$plugin_lang_dir = $plugin_name . '/langs';
load_plugin_textdomain( $plugin_name, false, $plugin_lang_dir );
これがシンプルで良いかと。
もし、私と同じようにプラグインやテーマで一部だけ多国語化されない症状に陥ったら、この記事を参考にして確認してみると解決できるかもしれない。