MyMiniCity踏んでください!!

ただいま絶賛MyMiniCity参加中です.是非リンクを踏んでください!!(笑
April 17th, 2006

PHPでメッセージカタログはgettextしかありえないでしょ

(Read: 17305)
Add to Hatena Bookmark

参照: Benchmarking PHP Localization - Is gettext fast enough? ?? Pablo’s Development Blog
いわゆるPHP配列なメッセージカタログとgettext拡張モジュール拡張モジュール,gettextのpo形式を扱うPHPスクリプトの3つを用いたベンチマーク.
「the PHP gettext extension is the fastest solution.」
だそうで,結果gettext拡張モジュールが一番早い.
当然の結果です.まぁPHPスクリプトでのメッセージカタログも配列より「$message = "メッセージ";」の方がさらに早いだろうけどそんな形式メンテナンス性悪すぎるのでステでそ.define()も等価.
理由は使用している全メッセージの取得が著しく行いづらい.

とりあえず第10回PHP勉強会でもでてきたのですが,
下記は「私がなぜgettextにこだわるか」ってところです.

gettextってそんなにいいのか?

ぶっちゃけgettextが完璧だ!!というわけではないです.現時点消去法で一番マシなのです.
理由は下記のとおり.

・英語メッセージカタログ(以後カタログ)の更新がほとんど確実に追跡できる
・カタログテンプレートの作成は当然更新と最新カタログと既存の翻訳カタログのマージが簡単.
・各種ユーティリティが豊富にそろっている

gettextでなければカタログの追跡は難しいのか?

答えは「yes」です.とりあずありがちなPHPスクリプトでカタログを扱う例を出してみます.
とりあえず英語のカタログは便宜上「en.php」というファイル名ということにしましょう.


$what_is_foo = "What is foo";
簡単な英語ですね.ごめんなさいボキャブラリ少なくて(痛
では翻訳しましょう.


$what_is_foo = "foo って何ぞや";
馬鹿みたいに簡単です.同様に便宜上「ja.php」というファイル名にします.
ここでen.phpで「?」を付け忘れていることに気づきました.
ってことで,変更します.


$what_is_foo = "What is foo?";
さてja.phpのメンテナンスをしている人はどうやればこれに気づくことができるでしょうか?
基本的に「変更したよ!!」って明言されないと気づきません.あるいはカンで気づいて見るかもしれません.
でも1000とかメッセージあるとわかりませんよね.
この原因は翻訳元と翻訳先のメッセージに関連付けがまったくないことから起こります.
PHPスクリプト的には


echo $what_is_foo;
なりすることで「カタログ変数の各言語共通化」できますが,「翻訳される実際のメッセージ」はすべての言語で関連性がないのです.

余談になりますが,私はCVSやsvnが使用できる環境の場合,翻訳作業で下記のように擬似タグを挿入します.

// EN-Revision: <en-revision>
$what_is_foo = "What is foo?";
<en-revision>はen.phpのリビジョン番号を入れます.
そうすれば下記のようにすることで最新と最終翻訳の差分を取得することができます.


$ cvs diff <en-revision> en.php
後はこれをリダイレクトしたりしてちまちまと作業をします.
しかし正直diff読みながら作業は面倒です.
こういう仕組みが作れないときは,旧バージョンのアーカイブと新バージョンのアーカイブの比較になります.
まぁ結局やることは似たようなもんですね.リポジトリが公開されてアクセスできると一度に一気に作業しなくていいので負担が少ないってのはメリットですが.

じゃー単なる変数じゃなく配列にすればいいじゃん!!
えらい!!よく気づきました.


$messages = array(
"What is foo"=>"What is foo"
);
とかやっておいて使用するときは


echo $message[ "What is foo"];
などとする.関数化してもいいですね.


function mes( $string) {
return isset( $GLOBALS[ "message"][ $string])?
$GLOBALS[ "message"][ $string]: $string;
}
echo mes( $message);
これならハテナを付けたくなれば


$messages = array(
"What is foo?"=>"What is foo?"
);
とすればいいですね.
これでカタログキーが変わるので,何らかのユーティリティを自作できそうです.
en.phpの連想キーとja.phpの連想キーの差分を取るとか.
でもこのen.phpの変更をja.phpに反映させ,「英文があれば未翻訳だよー」とか「連想キーと値が同じなら未翻訳ですよー」位したくないですか?
しかしそこまでツール作るとなるとちょっと面倒ですよね.
大体「英文のまま」イコール「未翻訳」ではないですし.「連想キーと値が同じなら未翻訳」ではありません.


$messages = array(
"SQL"=>"SQL"
);
とか.こういうのをしようとするとメッセージ毎に「翻訳済」「未翻訳」などをマーキングできなければなりません.
そんなことを配列でやってるとそもそもメッセージ自体の可読性が落ち,翻訳どころではありません.
ついでに忘れてませんか? プログラミングをしているときにわざわざ手動でカタログを作り直すんですか?
メッセージ摘出ツールが欲しいですよね.自作するんですか?
厳密にはgettextの摘出ツール(xgettext)を利用したり,「摘出するだけ」なら何らかの手段はあると思います.

結論

この辺で大体まとめてみます.

・ただのPHP変数で定義する「$message = "message";」という形式はメッセージ文(ここでは「message」)が変化しても追跡することが難しい
・配列にすると追跡できるが,翻訳の更新をすることが難しい
・どのみち未翻訳管理などができない
・カタログ作成ツールがない
・カタログを実際の各言語のカタログへの反映ツールがない

ということになります.
さて長くなったので一旦終わり.
次にgettextならどうなるのか辺りを.


▼ この記事へのコメント ▼
勉強になります。

PHP の配列やDBにメッセージリソースを格納する方法で、翻訳者が簡単に未翻訳部分をチェックしたり更新したりできる支援ツールがないのかなと思ってるのですが、見つけられていません。ツールのある gettext を使え、ということなんですかね。

あと、柿 -> 下記 ですね


ご指摘ありがとうございます > 柿

#「夏季」を修正したら「柿」になったとはトホホ

配列版カタログの編集はdotProjectでできます.もしかしたら余計な機能が多いけど(本来グループウェアだし)使えるかもしれませんね.

出てきてないけどdefine版カタログはXOOPSでモジュールがあった気がしますが既に追いかけるの辞めた後に出てきたので名前が分かりません(苦笑

DB版カタログで汎用で使えそうなのはあまり知らないですが,phpWebSiteがカタログをDBで持ちます.
といってもできが悪すぎるんですがあれ(苦笑

ありがとうございます。DB管理ではお薦めがないということですかね(笑)

ということで次の gettext 解説を心待ちにしてます。

トピックの参照元

▼最近のトピック

▼ 人気のトピック


< 過去の記事 [ 4All Categories ] 新しい記事 >
Powered by gsblog (customize)

[ POST ] [ AddLink ] [ CtlPanel ]

Subscribe blog

Bookmark blog

About me

about me

応援しています

我が息子が産まれたアクア・バースハウス(東京都世田谷区にある助産院)を応援しています.

翻訳のお仕事

腕に自信がある方,修行をしたい方はこちらをどうぞ.

2006 calendar

4月
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
| Day | Month | Year |

Powered by RRDTOOL.

Archives

Categories

Links


Mail to admin

人気ブログランキングへ RSS feed meter for http://blog.poyo.jp/ Search Engine Optimization
blogpeople.netに登録!! スカウター : よくきたblog

My Google news

My Google News

Related site

ころんころん♪ べびぽよ フォト蔵Wiki
string(40) "/categ-1/year-2006/month-4/id-1145244732"