Zend Frameworkではデータ検証用クラスとしてZend_Validateが用意されています。日ごろ使いそうな検証はほぼ揃っているのでありがたく使わせてもらっているのですが、残念ながらこのZend_Validateには日本語のエラーメッセージが実装されていません。なのでエラーメッセージの日本語化を自分で行う必要があります。 Zend Frameworkではメッセージの多言語化を行うためにZend_Translateというクラスが用意されているので、今回はこのZend_Translateを用いてZend_Validateの日本語化を行ってみます。
まずZend_Translateを用いてメッセージの他言語化を行う場合、メッセージの翻訳データを用意する必要があります。そしてZend_Translateではその翻訳データの種類に合わせて多くのアダプターが用意されています。私は今までプログラムの翻訳作業等やったことがないので、とりあえず一番使われていそうなGettextアダプタを使用してみることにします。gettextについての解説は下記サイトが大変参考になりました。
GNU gettextユーティリティ
gettextで翻訳作業を行うために、まずPOファイルと言うものが必要になります。gettext関数を用いて書かれたプログラムであればxgettextなどを用いて自動で翻訳のもとになるメッセージを抽出できるようなのですが、今回はクラスで定義されたプロパティからメッセージを抽出する必要があるので、自作でZend_Validateからメッセージを抽出するプログラムを作ってみました。POファイルはテキストファイルなので手作業で作る事も出来るのですが、今後Zend_Translateのクラスが増えたり、メッセージが増えたりする事があるかもしれませんのでこのようにプログラムを組んでおくと楽なんじゃなかろうかと思います。
xgettext.pl
#!/usr/bin/perl
use File::Basename;
my $start;
my $basename;
my %texts;
while (<>) {
chomp;
if (/\$_messageTemplates = array\($/) {
$start = 1;
next;
} elsif ($start) {
if (/\);$/) {
$start = 0;
next;
}
s/^.*=> ('|")([^\1]*)\1,?$/$2/;
$basename = basename(${ARGV});
push @{$texts{$_}}, $basename . ':' . $.;
}
if (eof) {
close(ARGV);
}
}
print "msgid \"\"\n";
print "msgstr \"\"\n";
print "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
print "\"Content-Transfer-Encoding: 8bit\\n\"\n\n";
foreach $key (sort keys %texts) {
foreach my $file_name (@{$texts{$key}}) {
print "#: ${file_name}\n";
}
print "msgid \"${key}\"\n";
print "msgstr \"\"\n\n";
}
PHPのフレームワークの解説なのにperlで実装してしまいました。私の中でコマンドラインのプログラムを書く際はシェルスクリプトかperlで書くという掟があるのです。許して下さい…。
./xgettext.pl lib/Zend/Validate/* > validate.po
とコマンドラインでやってもらえるとPOファイルが作成できます。
ちなみに現在のZend Frameworkの最新版(1.7.1)でのPOファイルはこんな感じです。
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: EmailAddress.php:58
msgid "'%hostname%' does not appear to have a valid MX record for the email address '%value%'"
msgstr ""
#: EmailAddress.php:57
msgid "'%hostname%' is not a valid hostname for email address '%value%'"
msgstr ""
#: EmailAddress.php:61
msgid "'%localPart%' is not a valid local part for email address '%value%'"
msgstr ""
#: EmailAddress.php:59
msgid "'%localPart%' not matched against dot-atom format"
msgstr ""
#: EmailAddress.php:60
msgid "'%localPart%' not matched against quoted-string format"
msgstr ""
#: Hostname.php:74
msgid "'%value%' appears to be a DNS hostname but cannot extract TLD part"
msgstr ""
#: Hostname.php:71
msgid "'%value%' appears to be a DNS hostname but cannot match TLD against known list"
msgstr ""
#: Hostname.php:73
msgid "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'"
msgstr ""
#: Hostname.php:72
msgid "'%value%' appears to be a DNS hostname but contains a dash (-) in an invalid position"
msgstr ""
#: Hostname.php:77
msgid "'%value%' appears to be a local network name but local network names are not allowed"
msgstr ""
#: Hostname.php:70
msgid "'%value%' appears to be an IP address, but IP addresses are not allowed"
msgstr ""
#: Digits.php:61
msgid "'%value%' contains not only digit characters"
msgstr ""
#: Float.php:45
msgid "'%value%' does not appear to be a float"
msgstr ""
#: Ip.php:41
msgid "'%value%' does not appear to be a valid IP address"
msgstr ""
#: Date.php:60
msgid "'%value%' does not appear to be a valid date"
msgstr ""
#: Hostname.php:76
msgid "'%value%' does not appear to be a valid local network name"
msgstr ""
#: Int.php:41
msgid "'%value%' does not appear to be an integer"
msgstr ""
#: Date.php:61
msgid "'%value%' does not fit given date format"
msgstr ""
#: Regex.php:45
msgid "'%value%' does not match against pattern '%pattern%'"
msgstr ""
#: Hostname.php:75
msgid "'%value%' does not match the expected structure for a DNS hostname"
msgstr ""
#: Alnum.php:68
msgid "'%value%' has not only alphabetic and digit characters"
msgstr ""
#: Alpha.php:68
msgid "'%value%' has not only alphabetic characters"
msgstr ""
#: Hex.php:49
msgid "'%value%' has not only hexadecimal digit characters"
msgstr ""
#: Alnum.php:69
#: Alpha.php:69
#: Digits.php:62
msgid "'%value%' is an empty string"
msgstr ""
#: StringLength.php:47
msgid "'%value%' is greater than %max% characters long"
msgstr ""
#: StringLength.php:46
msgid "'%value%' is less than %min% characters long"
msgstr ""
#: EmailAddress.php:56
msgid "'%value%' is not a valid email address in the basic format local-part@hostname"
msgstr ""
#: Between.php:54
msgid "'%value%' is not between '%min%' and '%max%', inclusively"
msgstr ""
#: GreaterThan.php:45
msgid "'%value%' is not greater than '%min%'"
msgstr ""
#: LessThan.php:45
msgid "'%value%' is not less than '%max%'"
msgstr ""
#: Date.php:59
msgid "'%value%' is not of the format YYYY-MM-DD"
msgstr ""
#: Between.php:55
msgid "'%value%' is not strictly between '%min%' and '%max%'"
msgstr ""
#: Ccnum.php:61
msgid "'%value%' must contain between 13 and 19 digits"
msgstr ""
#: InArray.php:45
msgid "'%value%' was not found in the haystack"
msgstr ""
#: Ccnum.php:62
msgid "Luhn algorithm (mod-10 checksum) failed on '%value%'"
msgstr ""
#: Identical.php:47
msgid "No token was provided to match against"
msgstr ""
#: Identical.php:46
msgid "Tokens do not match"
msgstr ""
#: NotEmpty.php:45
msgid "Value is empty, but a non-empty value is required"
msgstr ""
この作成したPOファイルのmsgidに対する日本語訳を下記のようにmsgstrに記述していきます。
#: StringLength.php:47
msgid "'%value%' is greater than %max% characters long"
msgstr "%max%文字以下で入力して下さい"
全ての日本語訳が完成したらmsgfmt等を用いてMOファイルを作成します。
msgfmt -o validate.mo validate.po
msgfmtに関しても詳しい事は上記『GNU gettextユーティリティ』にて解説してありますので参考にしてみて下さい。
以上で翻訳データの準備は完了です。後はこの翻訳データを用いてZend Frameworkでのエラーメッセージの日本語化を行います。
まず翻訳データを格納するディレクトリの構造を決める必要があります。
Zend Frameworkでは次の5つの構造を推奨しています。
- 単一構造のソース
- 言語ごとに分けた構造
- アプリケーションごとに分けた構造
- Gettext 形式の構造
- ファイル構造のソース
今回アダプターとしてGettextを選びましたので『Gettext 形式の構造』を選ぼうかと思ったのですが”LC_MESSAGES”の存在意義が見いだせなかったので『 言語ごとに分けた構造』にしてみました。
/languages
/ja
validate.mo
あとはindex.phpなどでZend_translateオブジェクトを作りZend_Validate_AbstractにDefautlTranslatorとして登録するだけです。
$translate = new Zend_Translate('gettext', '/var/www/html/languages', null, array('scan' => Zend_Translate::LOCALE_DIRECTORY));
Zend_Validate_Abstract::setDefaultTranslator($translate);
注意事項としてZend_Translateの第二引数として渡しているパスは翻訳データを格納しているディレクトリまでの絶対パスで指定して下さい。
以上でZend_Validateのエラーメッセージの日本語化は終了です。
記述した内容でおかしなところ等あればコメント残して頂けると喜びます!!