[php] Gettext + Poedit で多言語化

カナに切り替えるのが面倒で全部半角英数で作ったらいたく不評だった、なんて経験あるかもしれない。

翻訳前(en)

じゃせめてUIくらいは日本語にするか…と思ったなら、ローカライズしとけば一石二鳥じゃないか? 😀

wordpressのテンプレートファイルを翻訳する方法と似たような方法で普通のPHPウェブページやCGIも多言語化出来る。
gettextで検索するとコマンド-xgettextを使う方法が出てくるが、Windowsじゃ使えないし目も疲れるし
Poeditという素晴らしいソフトがあるのでコマンド使わずに出来る方法をメモっておくことにする。

続きを読む前にPoeditを公式サイトからダウンロードしてインストールしよう。
シンプルなアプリケーションだからそう難しくはないはず。

PHPでの準備

ページでもアプリケーションでも大抵1つは先頭でincludeなりrequireなりしている共通ファイルがあると思う。

そういうファイルに(無かったらlocalize.phpとかで作って)次のソースを入れる。

$lang = mb_substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2);

if ($lang=='en') $language = 'en_US';
else $language='ja_JP';

$locale = (isset($_GET['lang']))? $_GET['lang'] : $language;

putenv("LC_ALL=$locale");
setlocale(LC_ALL, $locale);

// ドメイン設定
textdomain("default");

// ドメインに対応するmoファイルのディレクトリ
bindtextdomain("default", "./locale");

各関数の詳しい説明はPHPマニュアルを見てください。

ドメイン設定はとりあえずPoeditの初期値であるdefaultにしてあるが、
単純に翻訳(mo)ファイルのファイル名だから好きな名前をつけてよい。

上記設定を行うと、翻訳ファイルの置き場所は
http://example.com/locale/ja_JP/LC_MESSAGES/default.mo
になるので、先にディレクトリだけ作っておく。

翻訳したい場所の修正

Poeditは指定されたディレクトリ内のファイルを捜査して設定したキーワード中の文字列をピックアップする。
翻訳文字列の出力はデフォルトがgettext()という関数で、省略形が_()なので
後者を使って翻訳したい場所を次のように修正する。

<title><?php echo _('WTN*Gettext DEMO');?></title>

でもechoとかprintっていちいち書くの面倒くさいからWordpressに習って関数を作る。

function _e($text)
{
	echo gettext($text);
}

function __($text)
{
	return gettext($text);
}

これで_e()と書けば出力までされるようになる。(アンダーバー2つの方は後の説明で出てきます)

<title><?php  _e('WTN*Gettext DEMO');?></title>

Poeditでの翻訳

  1. poEditを起動する
  2. 新規カタログ→プロジェクトの設定
    • プロジェクトの名前とバージョン→サイトの名前とか適当に
    • 翻訳チーム→自分の名前とか
    • 言語→Japanese
    • 国→JAPAN
    • 文字符号化&ソースコードの(ry→UTF-8
    • ページのパス→「ドット」だけ
    • パス→「新しいアイテム」で「ドット」(もしくは翻訳したいファイルがあるディレクトリ名)
    • キーワード→「__(アンダーバー2つ)」「_e」
  3. OKしてルートディレクトリに保存。ファイル名はtextdomainの設定と同じにする。
  4. 自動的に翻訳文が取り込まれる
  5. ひたすら翻訳
  6. 保存したら自動的にmoが作成・更新されるので/locale/ja_JP/LC_MESSAGES/以下に移す

よーしpoファイルとmoファイルできたどぅ~

poedit

で、見ると盛大に文字化けしてたりする。

gettext 文字化け

windowsはshift-jisでlinuxは鯖の影響を受けるらしい。
ならmb_convert_encodingで変換してしまえばいい…ってことで先に作った関数を修正

//translation
function _e($text)
{
	echo mb_convert_encoding(gettext($text),'UTF-8','AUTO');
}

function __($text)
{
	return mb_convert_encoding(gettext($text),'UTF-8','AUTO');
}

Warning: mb_convert_encoding(): Unable to detect character encoding~ってエラーが出たらmb_languageも追加しておく。

mb_language("Japanese");

Demo

View Demo

Before:
翻訳前(en)

After:
翻訳後(ja)

言語切り替えのソース(下記ライブラリより拝借)

$supported_locales = array('en_US', 'ja_JP');
print '<p id="locale">';
	foreach($supported_locales as $l) {
		print "[ <a href=\"?lang=$l\">$l</a> ] ";
	}
print "</p>\n";

gettextライブラリ

中にはgettextモジュールがインストールされていないサーバーがあるかもしれない。
そんなときにはライブラリ。

Gettext emulation in PHP

WordPressで利用されているものです。

「[php] Gettext + Poedit で多言語化」への4件のフィードバック

  1. いつも大変参考になる記事をご提供頂きありがとうございます。
    こちらの「[php] Gettext + Poedit で多言語化」の記事を見ながら見よう見真似で同等のことが出来ました。
    そこで質問ですが、ページを移動するとデフォルトの言語に戻りますが、ページ移動時も選択言語を保持するためにどのような処理が出来ますでしょうか?
    大変雑多で不躾な質問かと思いますが、何かアイデアなど頂けると助かります。宜しくお願いします。

    返信
  2. KM さん >

    URLに $_GET[‘lang’] を含めるか、同等の値をCookieで記憶させれば維持できます。
    どちらかというと再訪問時にも流用可能なCookieの方がスマートだと思います。

    返信
  3. ご親切にご返答いただきありがとうございます。
    なんとか手探りですがCookieの方をチャレンジしてみようと思います。
    次の投稿楽しみにしております。

    返信
  4. 一年以上前の投稿へのコメントで恐縮ですが、
    上記コメントにある「同等の値をCookieで記憶させれば維持できます」の部分の
    やり方ご教授いただくことはできませんでしょうか?
    何卒お願い致します。

    返信

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください