プラグインの翻訳ファイルを確実に適用させるベストな方法(メモ)

公開日:2024(令和6)年10月5日/最終更新日:

WordPress Customize Ideas | Personal WP Customization Notes (PWCN)

【景品表示法に基づく表記】ページ内のコンテンツには、商品プロモーションが含まれています



WordPressに追加したプラグインの翻訳は、プラグインの言語フォルダなどに入れたファイルを読み込ませるか、サイト本体の翻訳ディレクトリにファイルを入れるかのいずれかで適用されるようになるのはご存じかと思います。

一般的にプラグインの翻訳を適用させる場合は以下のようなコードをプラグイン内に書きますね。

function pwcn_load_textdomain() {
	load_plugin_textdomain(
		'テキストドメイン名',
		false,
		dirname( plugin_basename( __FILE__ ) ) . '/languages'
	); 
}
add_action( 'plugins_loaded', 'pwcn_load_textdomain' );

これが、WordPress6.7以降では「plugins_loaded」にフックさせていると以下のように表示されたり、エラーログに記録されたりするようになるようです(以下はWordPress 6.7Beta1時点で実際に表示されたものです)。

Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the [texdomain name] domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /…/wp-includes/functions.php on line 6099

日本語に訳すと

注意: 関数 _load_textdomain_just_in_time が誤って呼び出されました。[texdomain名] ドメインの翻訳の読み込みが早すぎました。これは通常、プラグインまたはテーマのコードが早すぎたことを示しています。詳細については、WordPress のデバッグを参照してください。(このメッセージはバージョン 6.7.0 で追加されました。) /…/wp-includes/functions.php の 6099 行目

と書かれており、読み込みが早すぎるということのようです。

まあNoticeなので警告でもエラーでもないので、様子見でもいいとは思いますが、エラーを調べるためにデバッグモードを有効にしていると基本的に毎度表示されてしまう(ログ出力している場合にはログがどんどん増える)ので、気になる人は対処しておきたいものだと思います。

これを回避するには「plugins_loaded」よりも遅い(テーマの設定情報が読み込まれた後に発火する)「after_setup_theme()」や「init()」を使えばOKなのですが、そうすると、ブロックエディターなどに追加したブロックスタイルなどの翻訳が効かなくなることがあります(私がテストした限りではこの事象が発生するケースがありました)。

この問題も回避して確実に翻訳を適用する最も正確な方法としては、サイトの翻訳ディレクトリ(「wp-content」→「languages」→「plugins」)へファイルを適用することではあるものの、公式のプラグインとして登録しているものでない場合には、もちろん自動で翻訳は落ちてこないですし、そこここで紹介されている「upgrader_process_complete()」関数は、プラグイン一覧から更新を走らせた時だけ有効のようで、アップロード更新時には動作しないので、その方法も使えません。

そこでいろいろと試行錯誤して、WordPress公式のプラグインディレクトリ上で配布していない(いわゆる野良プラグイン)でもこの不具合を解消する方法を見つけましたので参考までに公開しておきます。

お断りしておきますが、公開時点でWordPress6.7はベータ1バージョンであり、公式リリース時にどうなっているのかも分かりませんし、あくまでも私の場合の解決法ですのでそのあたりを承知の上で読んでいただければと思います。

自作プラグインでなければ対処を待つしかない

本ページの主旨である自作プラグインでの対処方法については次項以降で紹介しますので、この項は読み飛ばしてください

すべて読んでいただければわかると思いますが、これはプログラムに対して指摘されている事柄ですので、WordPress公式サイトからインストールしたプラグインやテーマの場合には、自力で改善するのではなく、プラグイン作者が気づいて対応バージョンがリリースされるのを待つのがよいでしょう。

それよりも、この注意事項が出るということは、デバッグモードがオンになっているということで、この注意に限らずエラーや警告が出た場合には閲覧者にも表示され、どこでエラーが出てるのかやサーバー内の階層なども晒してしまうことになりますから、デバッグモードをオフにすることをおすすめします。

また、表示はさせずに記録だけして後から確認できるようにするには以下のようにするといいでしょう。

現行のコードの修正ポイント

私の環境での話ではありますが、冒頭のコードで翻訳ファイルを適用させている場合で、以下のようなコードがある時に注意表示が出ることが確認できました。

どうやら注意表示の本当の意味は、翻訳ファイルの適用タイミングではなく、プログラム内での翻訳文字列の割り当て方の問題だったようです。

$text = __('aiueo','textdomain');

<?php esc_html_e( $text ); ?>

_eというのはechoの代わりに使うもので、公式によれば、この場合は変数でテキストドメインの指定はしているものの、呼び出される_e関数の中でテキストドメインの指定がないために警告が出るようです(6.6.xでは出ていなかったので間違いなく6.7のチェックで引っかかるようになったと思います)。

これを解消するには、_e関数を使わずに、素直に以下のようにすることです。

$text = __('aiueo','textdomain');

<?php echo esc_html( $text ); ?>

恐らくエラーの意味としては、echoして翻訳対処となる変数化した文字列が指定されているものの、echo時にはテキストドメインがなく、変数の読み込み時にテキストドメインが割り当てられているので、「タイミングが早すぎる」と判定されているのでしょう。

その他でも出るかもしれませんが、一応私の作成するプラグインでは引っかかった事象でしたので、同じような状況の方は改善してみるといいかも知れません。

またこの警告が出る原因については、以下のプラグインの「一般」項目でチェックするとエラーとして指摘されますから活用することをおすすめします。

サイト本体の翻訳ファイルと比較して上書きを行う

上記の方法でも解消しないという場合には以下の方法が有効でしょう(私は今後同様のトラブルが起きないようこの方法に統一しました)。

WordPress公式サイトから入手でき、翻訳が可能なプラグインでは使えない方法ですのでご注意ください

この不都合というか不具合を解消するには、プラグインディレクトリ内に設置した翻訳ファイル用のディレクトリ(通常は「languages」ディレクトリ)にある翻訳ファイルをサイト本体の翻訳ディレクトリ(「wp-content」→「languages」→「plugins」)へコピーする機能を設けることです。

さらに、プラグインディレクトリ側の翻訳を正として、本体の翻訳ディレクトリと比較し、古い場合には上書き更新するという機能も必要になります。

以下が対応用コードです。

* プラグインの読み込み時に翻訳ファイルを確認して更新 */
/* アップロード更新の場合に「upgrader_process_complete」フックは効かないためにこの措置にした */
/* プラグインディレクトリ側のファイルと、本体の翻訳ディレクトリ側のファイルの日付を比較して更新 */
function pwcn_update_languages_files() {
	$lang_dir = WP_LANG_DIR . '/plugins/';
	$locales = [
		'ja' => ['ここに正式な翻訳ファイル名'],
		//ロケールが追加されたらここにファイルの配列を追加
	];
	$source_dir = plugin_dir_path(__FILE__) . 'languages/';

	foreach ($locales as $locale => $files) {
		foreach ($files as $file_name) {
			$source_file = $source_dir . $file_name;
			$target_file = $lang_dir . $file_name;

			if (file_exists($source_file)) {
				// ターゲットファイルが存在する場合、日付を比較
				if (file_exists($target_file)) {
					if (filemtime($source_file) > filemtime($target_file)) {
						// プラグイン内のファイルが新しい場合はコピー
						copy($source_file, $target_file);
					}
				} else {
					// ターゲットファイルが存在しない場合はコピー
					copy($source_file, $target_file);
				}
			} else {
				error_log("Translation file not found: " . $source_file);
			}
		}
	}
}
add_action('plugins_loaded', 'pwcn_update_languages_files');

上記のコードはプラグインディレクトリ内に「languages」ディレクトリがあり、そこに翻訳ファイルがある場合ですので、異なる場合には10行目付近の「languages」の文字列を適切なディレクトリへ書き換える必要があります。

また、「ここに正式な翻訳ファイル名」の部分には翻訳ファイル名と拡張子を記述する必要があります。

.mo .l10n.php .jsonなど複数のファイルがある場合には、「,」で区切って追加します。

例:’〇〇-ja.mo’, ‘〇〇-ja.po’, ‘〇〇-ja.l10n.php’,’〇〇-ja.json’

これで、基本的にこのコードを設置しておけば、管理画面で画面遷移したり、フロントエンドへのアクセスがある度(要はそのプラグインがロードされる度)に

  • サイトの翻訳ディレクトリにファイルがなければ追加
  • サイトの翻訳ディレクトリにあるファイルよりもプラグインの翻訳フォルダにあるファイルが新しければ書き換え

という動作をしますから、常に最新の状態を保つことができます。

そもそも元の翻訳ファイルの読み込みで「plugin_loaded」にフックさせて似たようなことをしていたわけですから、特に動作に負荷がかかるということもないでしょう。

また、このコードを書いておくことで、サイトの翻訳ディレクトリにある翻訳は特別に読み込まなくても確実にサイトへ読み込まれますから、以下のような翻訳ファイル読み込みのコードも不要になります。

逆にinitで読み込ませた場合には一部の翻訳が効かないというトラブルが発生する可能性があるので書かない方が無難かも知れません。

function pwcn_load_textdomain() {
	load_plugin_textdomain(
		'テキストドメイン名',
		false,
		dirname( plugin_basename( __FILE__ ) ) . '/languages'
	); 
}
add_action( 'plugins_loaded', 'pwcn_load_textdomain' );
または
add_action( 'init', 'pwcn_load_textdomain', 1 );

さらに、プラグインを使わなくなった時にサイトの翻訳ディレクトリへ余分なファイルを残さないよう、以下のようなコードを使ってプラグインの停止(削除)時にそれらのファイルを削除するようにしておくといいでしょう。

/* プラグイン無効化時に翻訳ファイルを削除 */
function pwcn_delete_languages_files() {
	$lang_dir = WP_LANG_DIR . '/plugins/';
	$locales = [
		'ja' => ['ここに正式な翻訳ファイル名'],
		// 他のロケールを追加
	];

	foreach ($locales as $locale => $files) {
		foreach ($files as $file_name) {
			$file_path = $lang_dir . $file_name;

			if (file_exists($file_path)) {
				unlink($file_path);
			}
		}
	}
}
//register_uninstall_hook(__FILE__, 'pwcn_delete_languages_files');//削除時
register_deactivation_hook(__FILE__, 'pwcn_delete_languages_files');//停止時

ここまでWordPress6.7で発生するNoticeとなる事項を予見して書いてきましたが、そうでなくても基本的にこのコードで書いておけば問題は起きませんし、きちんと翻訳も当たるので、個人的にはこれが翻訳を確実に適用させるベストな方法だと思いますので、今後何かのプラグインを作る(配布する)際にはこの手法で行く予定です。

WordPress 6.8以降では対策を行う必要なくなるかも

詳しくはテストしていませんが、WordPress 6.8以降では以下のような条件を満たしている場合、load_*_textdomain()を使わなくても翻訳が適用されるようになるようです。

  • WordPress公式で配布されているプラグインやテーマ
  • プラグインやテーマヘッダー内に正しくText DomainとDomain Pathの記述がある場合

詳しくは以下のページなどを参照ください。

こちらも未確認ですが、load_*_textdomain()の記述は以下のような段取りになっているはずなので、独自の翻訳ファイルを適用させたいときはWordPressの翻訳ディレクトリ(wp-content→languages以下の適切な場所)へ入れておけば問題ないかと思います。

そういう意味でも本ページで提案している「サイト本体の翻訳ファイルと比較して上書きを行う」という措置は、若干のパフォーマンスへの影響(個人的にはほとんど影響は皆無だと考えていますが..)を除けば、確実に翻訳ファイルを読み込ませるベストな方法だといえるでしょう。

, , , , , , , , , , , , ,



Lolipop ServerMoshimo Ad x-serverMoshimo Ad

WordPress Customize Ideas | Personal WP Customization Notes (PWCN)
SEOへの影響を最小限にしながら行うパーマリンク変更の手順