はじめに
gettext化されていないプラグインやテーマのローカライズ作業をしているうちに、_e('foo bar', 'the-plugin') だの _e('jack', 'the-theme') と逐一ドメイン引数(第2引数)を入力するのは面倒極まりないので、省力化のためのコードを書きました。
プラグイン化していますが、自作プラグインに同梱配布してコードからinclude() / require()する、という使い方もいいでしょう。(その場合は、拡張子を “.php” から “.inc” に変更することをお勧めします。)
GPLライセンスです。
インストール
- l10n-helper プラグインのzipファイルをダウンロード
- wp-content/plugins/ディレクトリに展開
- adminパネルでプラグインを有効化
使用例
テーマファイルで…
<?php __theme('my-theme'); ?> <?php get_header(); ?> <div id="content" class="narrowcolumn"> <?php if (have_posts()) : ?> <?php while (have_posts()) : the_post(); ?> <div class="post" id="post-<?php the_ID(); ?>"> <h2><a href="<?php the_permalink() ?>" rel="bookmark" title="<?php __pf('Permanent Link to %s', get_the_title(); ?>"> ... <?php __r(); ?>
プラグインで…
<?php ... add_action('plugins_loaded', 'myplugin_init'); add_action('admin_footer', 'myplugin_adminfooter'); function myplugin_init() { __pluging('myplugin', dirname(__FILE__)); } function myplugin_adminfooter() { __s('myplugin'); echo '<p>'; __e('Did you know? '); echo myplugin_get_random_tips(); echo '</p>'; __r(); } ...
定義関数名について(2007/07/24追加)
l10n-helper では関数名の接頭辞としてアンダーバー2つ `__’ を採用しています。WordPress Japanフォーラムの yuriko 氏から、この接頭辞はphpが予約済みであり非推奨としているとの指摘を頂きました。
背景を理解しつつ、将来 php標準と名前が衝突することはまずありえない(標準関数名として非妥当)ということから、l10n helperでは利便性を重視し、現状の関数名を使用します。
なお、将来の名前衝突やその他のことが気になる方は、適宜名前を修正して使用されるとよいでしょう。
定義関数
- __s($textdomain)
- テキストドメイン使用ブロック開始
$textdomain: 使用するテキストドメイン
テキストドメイン使用ブロックを開始します。__s()?__r()で囲まれた部分をブロックと呼び、ブロック内で呼び出された翻訳関数(__e()など)は、ブロックの先頭で設定されたテキストドメインに属する翻訳テキストを抽出します。
テキストドメイン使用ブロックは入れ子にできます。(__s();__s();__r();__r()という呼び出しが可能。) __r()を呼ぶと、自動的に1つ前のテキストドメインに復帰します。
対になる__r()を呼び忘れないようにしましょう。 - __r()
- テキストドメイン使用ブロック終了
現在のテキストドメイン使用ブロックを終了します。__r()を呼ぶと、自動的に1つ前のテキストドメインに復帰します。
テキストドメインブロックは、__s()のほか、__plugin(),__theme()によっても開始します。
これらの関数を呼び出したら、必ず対になる__r()を呼びましょう。呼び忘れた場合、表示画面の一部が翻訳されない、または期待しない翻訳に置き換わる場合があります。 - __plugin($domain, $mo_dir)
- プラグイン用翻訳ファイルの読み込み、および、テキストドメインブロック開始
$domain: 使用するテキストドメイン
$mo_dir: プラグインと翻訳ファイルが格納されているディレクトリ
プラグイン用翻訳ファイル(*.mo)を読み込み、テキストドメインブロックを開始します。
翻訳ファイルはプラグインと同一のディレクトリに置かれていなければなりません。
また翻訳ファイル名は、<テキストドメイン>-<ロケール>.moの形式になっていないと読み込まれません。(例:myPlugIn-ja.mo,myPlugIn-fr_FR.mo)
この関数は内部で自動的に__s()を呼び出します。
テキストドメインブロックの最後で、対になる__r()を忘れずに呼び出しましょう。 - __theme($domain)
- テーマ用翻訳ファイルの読み込み、および、テキストドメインブロック開始
$domain: 使用するテキストドメイン
テーマ用翻訳ファイル(*.mo)を読み込み、テキストドメインブロックを開始します。
翻訳ファイルはテーマと同一のディレクトリに置かれていなければなりません。
また翻訳ファイル名は、<ロケール>.moの形式になっていないと読み込まれません。(例:ja.mo,fr_FR.mo)
この関数は内部で自動的に__s()を呼び出します。
テキストドメインブロックの最後で、対になる__r()を忘れずに呼び出しましょう。 - ___($text)
- 翻訳テキストを取得
$text: 翻訳前テキスト
戻り値: 翻訳後テキスト
現在のテキストドメインにおける翻訳ファイル(*.mo)を元に、翻訳テキストを取得します。
翻訳ファイルに定義されてないテキストを渡した場合、そのテキストがそのまま戻ります。 - __e($text)
- 翻訳テキストを出力(echo)
$text: 翻訳前テキスト
現在のテキストドメインにおける翻訳ファイル(*.mo)を元にテキストを翻訳し、出力(echo)します。
翻訳ファイルに定義されてないテキストを渡した場合、そのテキストがそのまま出力されます。 - __pf($fmt, $arg1, $arg2, …)
- 翻訳テキストをフォーマットして出力(echo)
$fmt: 翻訳前テキスト
$arg: フォーマット置き換え値(可変長引数)
PHP標準関数printf()を基にした翻訳関数です。現在のテキストドメインにおける翻訳ファイル(*.mo)を元にテキストを翻訳し、得られたテキストをprintf()を利用してフォーマットして出力(echo)します。
(例) __pf(’Hello, %1$s %2$s’, $first_name, $last_name);
フォーマットの書式についてはsprintf()のマニュアルを参照ください。
なお翻訳ファイルに定義されてないテキストを渡した場合、そのテキストがそのまま利用されます。 - __f($fmt, $arg1, $arg2, …)
- 翻訳テキストをフォーマットして取得
$fmt: 翻訳前テキスト
$arg: フォーマット置き換え値(可変長引数)
戻り値: 翻訳・フォーマット後の文字列
PHP標準関数sprintf()を基にした翻訳関数です。現在のテキストドメインにおける翻訳ファイル(*.mo)を元にテキストを翻訳し、得られたテキストをsprintf()を利用してフォーマットして呼び出し元に戻します。
(例) $text = __f(’Hello, %1$s %2$s’, $first_name, $last_name);
フォーマットの書式についてはsprintf()のマニュアルを参照ください。
なお翻訳ファイルに定義されてないテキストを渡した場合、そのテキストがそのままフォーマットに利用されます。 - l10n_helper__check_on_shutdown()
- デバッグ用途チェック関数
__s()/__plugin()/__theme()?__r()の呼び出しが正しく対になっているか確認します。
確認のタイミングは、PHPページの出力がすべて終わった時点です。
もしも__r()の呼び出しが過少または過多の場合、デバッグモードであればログに情報を書き込みます。
デバッグモードとは、グローバル変数 $debug が真に評価される場合のモードです。設定するには、wp-config.phpの先頭で、$debug = true;とします。
ログは、wp-config.php と同じディレクトリに、l10n-helper.logの名前で出力されます。
使用パターン
テーマファイルにて
もっとも単純かつ確実なのは、各テーマファイル(*.php)の先頭で __theme() を呼び、末尾で __r() を呼ぶ方法です。
<?php __theme('my-theme'); ?> ... <?php __r(); ?>
よりパフォーマンスを重視するならば(__theme() は最初の呼び出し時のみ特別な処理を行います。2回目以降は __s() と同等の処理をするだけですが、余分な処理を行う分、CPU時間をより消費します)、header.phpでのみ __theme() を使い、他のファイルでは__s() を使うようにします。
(your_theme/header.php)
<?php __theme('my-theme'); ?> ... call __e()/___()/__pf()/__f() ... <?php __r(); ?>
(your_theme/*.php)
<?php __s('my-theme'); ?> ... <?php __r(); ?>
__theme() を呼び出す前に __s() が呼ばれてしまうと、翻訳関数(__e()など)が正しく機能しません。header.php を読み込まないテーマファイルがある場合は、そのファイル内で __theme() を呼び出すなど、抜かりなく対処する必要があります。
プラグインにて
テーマファイルと同様に、単純な方法としては、翻訳が必要な各処理の前後で__plugin() と __r() を逐一呼ぶ方法があります。
もしくは、一度だけ __plugin() を呼び、以降は __s() を呼ぶ方法です。
前者は安全確実、後者は速度重視です。
[パターン A] __plugin() を毎回呼ぶ
<?php function myplugin_do_something() { ... __plugin('my_plugin_domain'); ... call __e()/___()/__pf()/__f() ... if (some_condition) { __r(); return; } ... __r(); }
[パターン B-1] プラグイン初期化時に __plugin() を呼ぶ
<?php add_action('plugins_loaded', 'myplugin_init'); function myplugin_init() { __plugin('my_plugin_domain'); __r(); // `__plugin()' は内部で `__s()' を呼ぶため、`__r()'の呼び出しが必要 } function myplugin_do_something() { ... __s('my_plugin_domain'); ... __r(); }
[パターン B-2] 翻訳処理の初回でのみ __plugin() を呼ぶ
(パターン B-1よりこちらの方が効率的になる可能性があります。なぜならプラグインの初期化処理を行ったとしても、プラグインの本体処理が呼び出されない場合もあるからです。)
<?php define('MY_PLUGIN_DOMAIN', 'my_plugin_domain'); function myplugin_do_something() { ... global $l10n; if (!isset($l10n[MY_PLUGIN_DOMAIN])) { __plugin(MY_PLUGIN_DOMAIN); } else { __s(MY_PLUGIN_DOMAIN); } ... __r(); }
[追伸] とはいうものの、昨今のサーバは処理速度が十分速くなっていますので、どの方法でも処理時間にあまり差がでないかもしれません。
