PHP標準のGettext
PHPで標準サポートされているGettextを試します。
ソースコードにメッセージIDを埋め込む
メッセージ文字列はソースコードには記述しません。ソースコードには、メッセージ文字列の代わりにメッセージIDを埋め込みます。埋め込みにはgettext
関数を使います(gettext
ではなく単に_
と書くこともできます)。最終的に出力したいメッセージ文字列が「タイトル」だったとしても、ソースコードには'タイトル'
ではなく_('title')
のように書くのです('title'がメッセージIDです)。
ここではcharset
とtitle
、hi %s %s.
という3つのメッセージIDを導入します(charsetはUTF-8に統一すべきなのですが、Windows版のPHPでは、Japanese_Japan.UTF-8が使えないため、charsetを操作できるようにしました。これはあまりよい方法ではありません)。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=<?php echo _('charset') ?>" /> <title><?php echo _('title') ?></title> </head> <body> <p><?php $firstName='Taro'; $lastName='YABUKI'; printf(_('hi %s %s.'),$firstName,$lastName); ?></p> </body> </html>
テンプレート
_
関数(あるいはgettext
関数)を含んだソースコードから、xgettext
コマンドを使ってメッセージIDを抜き出します(--from-codeで.phpファイルの文字コードを、-oで出力ファイルを指定しています)。
xgettext trans.php --from-code=utf-8 -o messages.pot
次のようなファイルmessages.potが生成されます。このファイルが、翻訳のためのテンプレートになります。
(略) "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: trans.php:16 msgid "charset" msgstr "" #: trans.php:17 msgid "title" msgstr "" #: trans.php:23 #, php-format msgid "hi %s %s" msgstr ""
POファイル(メッセージカタログ)
ロケールごとにメッセージカタログを置くためのディレクトリを作り、テンプレートをコピーします。
mkdir -p locale/Japanese_Japan/LC_MESSAGES mkdir -p locale/English/LC_MESSAGES cp messages.pot locale/Japanese_Japan/LC_MESSAGES/messages.po cp messages.pot locale/English/LC_MESSAGES/messages.po
各poファイルを翻訳します。charsetの部分も書き換えて、そこで指定した文字コードで保存してください。たとえば、日本語の場合は次のようになります(保存する文字コードの選択肢にWindows-31Jがないときは、Shift_JISでいいでしょう)。
(略) "Content-Type: text/plain; charset=Windows-31J\n" "Content-Transfer-Encoding: 8bit\n" #: trans.php:16 msgid "charset" msgstr "Windows-31J" #: trans.php:17 msgid "title" msgstr "タイトル" #: trans.php:23 #, php-format msgid "hi %s %s." msgstr "こんにちは、%2$s %1$s。"
英語の場合は次のようになります。
(略) "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" #: trans.php:16 msgid "charset" msgstr "ISO-8859-1" #: trans.php:17 msgid "title" msgstr "Title" #: trans.php:23 #, php-format msgid "hi %s %s." msgstr "Hello %s %s."
"hi %s %s."
の部分の違いに注目してください。英語の場合はメッセージIDと同じ順番(つまりfirstName、lastNameの順)なのでそのままでいいのですが、日本語の場合はlastName、firstNameの順にしなければならないので、数値$
という記法を使って順番を変えています。
MOファイル(バイナリファイル)
msgfmt
コマンドでPOファイルからMOファイルを作ります。メッセージ文字列はMOファイルから読み出されます。
pushd locale/Japanese_Japan/LC_MESSAGES msgfmt messages.po popd pushd locale/English/LC_MESSAGES msgfmt messages.po popd
MOファイルの利用
上で作成したMOファイルを利用するためには、少し準備が必要です。
まず、ロケールを設定します。ブラウザで最優先に設定されている言語が英語ならEnglishに、そうでなければJapanese_Japan.932に設定します(Japanese_Japan.UTF-8は使えません)。これはWindowsの場合です。Windows以外ではja_JP.UTF-8などの形式を利用できるでしょう(これはよい設定方法ではありません。後述のI18Nv2を利用する方法の方がよいでしょう)。
$tmp=mb_substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2); if ($tmp=='en') $language = 'English'; else $language='Japanese_Japan.932'; putenv("LANG=$language"); setlocale(LC_ALL, $language);
次に、利用するドメインを指定します。ドメインとはメッセージ文字列の管理単位のことで、ドメインとロケール、メッセージIDを指定することによって、メッセージ文字列が確定します。ドメイン名とMOファイルのファイル名は揃っていなければなりません。
$domain='messages'; bindtextdomain($domain, './locale');//ドメインとディレクトリの対応付け textdomain($domain);//ドメインを指定
以上をまとめると、PHPファイルは次のようになります。ブラウザの言語設定において、英語を最優先にすると英語のメッセージが、日本語を最優先にするとを日本語メッセージが表示されます。
<?php //言語とロケールの簡易設定 $tmp=mb_substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2); if ($tmp=='en') $language = 'English'; else $language='Japanese_Japan.932';//Japanese_Japan.UTF-8は使えない putenv("LANG=$language"); setlocale(LC_ALL, $language); //gettextの設定 $domain='messages'; bindtextdomain($domain, './locale'); textdomain($domain); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=<?php echo _('charset') ?>" /> <title><?php echo _('title') ?></title> </head> <body> <p><?php $firstName='Taro'; $lastName='YABUKI'; printf(_('hi %s %s.'),$firstName,$lastName); ?></p> </body> </html>