日本語サイトをベースに英語サイトを作成したとき、英語サイトのテーマディレクトリに翻訳ファイル(en_US.mo)を設置しました。
けれど、デバッグしてみると翻訳ファイルが読み込まれない。
その原因の調査結果、解決策です。(WordPress 4.8.1 - 4.9.6)
間違った設定を行っていないか確認
まず、設定が間違っていると調べる意味はないので確認します。
内容は次の通りです。
- __() or _e()は使っているか?
- __() or _e()の第2引数にドメインテキストが指定されているか?
- functions.phpの定義に間違いはないか?
- 翻訳ファイルの設置場所に間違いはないか?
__() or _e()の使い方に間違いはありませんでした。
<?php the_content(__('続きを読む', 'domain_name')); ?>
使い方はまちがってません。次にfunctions.phpの定義を確認しました。
/**
* 子テーマの翻訳ファイル定義
*/
function language_child() {
load_child_theme_textdomain( 'domain_name', get_theme_file_path( 'languages' ) );
}
add_action( 'after_setup_theme', 'language_child' );
内容に問題はありません。そもそも、前に別のテーマで使っていた定義をコピペしてきたものなので間違いはないはずです。
そのときは英語のテーマを日本語に翻訳したのですが、正常に動作していました。
英語用翻訳ファイルen_US.moファイルは、DocumentRoot/wp-content/themes/domain_name/languages/に設置しています。
設定に間違いありません。
こうなったらWordPressのソースを追跡する
この設定でなぜ翻訳ファイルが読み込まれないのか分かりません。悩んでてもラチがあかないのでソースコードを追います。
まずは、load_child_theme_textdomain()です。
load_child_theme_textdomain()
/**
* Load the child themes translated strings.
*
* If the current locale exists as a .mo file in the child themes
* root directory, it will be included in the translated strings by the $domain.
*
* The .mo files must be named based on the locale exactly.
*
* @since 2.9.0
*
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $path Optional. Path to the directory containing the .mo file.
* Default false.
* @return bool True when the theme textdomain is successfully loaded, false otherwise.
*/
function load_child_theme_textdomain( $domain, $path = false ) {
if ( ! $path )
$path = get_stylesheet_directory();
return load_theme_textdomain( $domain, $path );
}
ここでは、.moファイルの設置パスが未指定の場合、テーマのホームディレクトリを設定しているだけです。
次へ行きましょう。
load_theme_domain()
/**
* Load the theme's translated strings.
*
* If the current locale exists as a .mo file in the theme's root directory, it
* will be included in the translated strings by the $domain.
*
* The .mo files must be named based on the locale exactly.
*
* @since 1.5.0
* @since 4.6.0 The function now tries to load the .mo file from the languages directory first.
*
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $path Optional. Path to the directory containing the .mo file.
* Default false.
* @return bool True when textdomain is successfully loaded, false otherwise.
*/
function load_theme_textdomain( $domain, $path = false ) {
/**
* Filters a theme's locale.
*
* @since 3.0.0
*
* @param string $locale The theme's current locale.
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
*/
$locale = apply_filters( 'theme_locale', is_admin() ? get_user_locale() : get_locale(), $domain );
$mofile = $domain . '-' . $locale . '.mo';
// Try to load from the languages directory first.
if ( load_textdomain( $domain, WP_LANG_DIR . '/themes/' . $mofile ) ) {
return true;
}
if ( ! $path ) {
$path = get_template_directory();
}
return load_textdomain( $domain, $path . '/' . $locale . '.mo' );
}
$localeでは、日本語サイトはjp、英語サイトではen_USになります。
問題は、31行目のload_textdomain()です。ここでは、テーマディレクトリではなく、Document/wp-content/languages/themes/のdomain_name-en_US.moファイルを読み込もうとします。
デバッグをしたところ必ずtrueが返ってきます。指定したパスの.moファイル読み込みは、最終行で行われるので、これでは.moファイルを読み込むはずもありません。
load_textdomain()を見てみましょう。
load_textdomain()
/**
* Load a .mo file into the text domain $domain.
*
* If the text domain already exists, the translations will be merged. If both
* sets have the same string, the translation from the original value will be taken.
*
* On success, the .mo file will be placed in the $l10n global by $domain
* and will be a MO object.
*
* @since 1.5.0
*
* @global array $l10n An array of all currently loaded text domains.
* @global array $l10n_unloaded An array of all text domains that have been unloaded again.
*
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $mofile Path to the .mo file.
* @return bool True on success, false on failure.
*/
function load_textdomain( $domain, $mofile ) {
global $l10n, $l10n_unloaded;
$l10n_unloaded = (array) $l10n_unloaded;
/**
* Filters whether to override the .mo file loading.
*
* @since 2.9.0
*
* @param bool $override Whether to override the .mo file loading. Default false.
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $mofile Path to the MO file.
*/
$plugin_override = apply_filters( 'override_load_textdomain', false, $domain, $mofile );
if ( true == $plugin_override ) {
unset( $l10n_unloaded[ $domain ] );
return true;
}
/**
* Fires before the MO translation file is loaded.
*
* @since 2.9.0
*
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $mofile Path to the .mo file.
*/
do_action( 'load_textdomain', $domain, $mofile );
/**
* Filters MO file path for loading translations for a specific text domain.
*
* @since 2.9.0
*
* @param string $mofile Path to the MO file.
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
*/
$mofile = apply_filters( 'load_textdomain_mofile', $mofile, $domain );
if ( !is_readable( $mofile ) ) return false;
$mo = new MO();
if ( !$mo->import_from_file( $mofile ) ) return false;
if ( isset( $l10n[$domain] ) )
$mo->merge_with( $l10n[$domain] );
unset( $l10n_unloaded[ $domain ] );
$l10n[$domain] = &$mo;
return true;
}
問題は33行目です。
apply_filters( 'override_load_textdomain', false, $domain, $mofile );
これが必ずtrueを返します。これでは、設置した翻訳ファイルの内容が反映されません。
うしろの処理が行われません。
- .moファイルを読み込む
- オブジェクト(new MO)にマージした結果を格納
- グローバル変数$l10n[]に挿入
この行は、.moファイルの読み込みの上書きを無効にするかをフィルタリングします。
3番目の引数で上書きしない(false)にしているので、デフォルトはfalseを返すはずです。
ということは、別のどこかで'override_load_textdomain'のフックに対してtrueを返すようにしているのでは?と気づきました。
そこで、WordPressのDocumentRootディレクトリ全域で検索をかけました。
すると、BackWPupプラグインで "add_filter( 'override_load_textdomain', '__return_true' );" を記述している箇所が2つもありました。
テーマのfunctions.phpを修正する
これを修正する方法はかんたんです。テーマのfunctions.phpファイルに次の1行を追加します。
add_filter( 'override_load_textdomain', '__return_false' );
add_filterの第2引数で'__return_false'を指定すると、フィルタの関数で必ずfalseを返すようになります。
まとめ
原因はBackWPupプラグインにありました。プラグインの記述でテーマの翻訳ファイルにまで影響していました。
あとは自分のWordPressに対する知識不足でしょう。この投稿を最初に書いたときはWordPressを使い始めて間もないころで不慣れでした。
filterの使い方をあまり知らずに書いたため、必要のない暫定処理を書いていました。
きちんとした修正方法が見つかったので、これでWordPressのアップデートがあっても大丈夫です。
(暫定処理はWordpressのソースを直接編集していた。)
2018/07/18
暫定措置の内容を残そうとも思いましたが、最終的にたどり着いた原因・対策とかけ離れているので、ぜんぶ削除しました。
WordPress 4.8.2 にバージョンアップしたので同じような暫定措置を入れました。
WordPress 4.8.3にバージョンアップしたので同じような暫定措置を入れました。