なんだか寝れずに朝3時に起きてしまったので、書いてみる。
Perl で L10N といえば、Locale::Maketext::Lexicon ですが、間違った *.po ファイルを Gettext で指定すると、これでもかってくらいに探しまくるんですよね。例えば、実際に使いたい strings.po は /doko/soko/strings.poなのに、間違って /soko/strings.poを指定したとします。こんな感じ
package Hello::I18N::de;
use base 'Hello::I18N';
use Locale::Maketext::Lexicon (Gettext => '/soko/strings.po');
1;
すると、Gettext が SCALAR なので、Locale::Maketext::Lexicon::lexicon_get_() が呼び出されるんですが、ここでのファイルが見つからなかったときの探し方が。。
my @path = split( '::', $caller );
push @path, $lang if length $lang;
$src = (
grep { -e } map {
my @subpath = @path[ 0 .. $_ ];
map { File::Spec->catfile( $_, @subpath, $src ) } @INC;
} -1 .. $#path
)[-1]
unless -e $src;
@INC で map して grep して -e って。$caler は scalar caller で定義されて Locale::Maketext::Lexicon が入ってるんだけど、結局のところ、たとえば手元の環境だと
/usr/lib/perl5/5.8.8/i686-linux/Locale/soko/strings.po /usr/lib/perl5/5.8.8/Locale/soko/strings.po /usr/lib/perl5/site_perl/5.8.8/i686-linux/Locale/soko/strings.po /usr/lib/perl5/site_perl/5.8.8/Locale/soko/strings.po /usr/lib/perl5/site_perl/5.8.5/Locale/soko/strings.po /usr/lib/perl5/site_perl/5.8.4/Locale/soko/strings.po /usr/lib/perl5/site_perl/5.8.3/Locale/soko/strings.po /usr/lib/perl5/site_perl/5.8.2/Locale/soko/strings.po /usr/lib/perl5/site_perl/5.8.1/Locale/soko/strings.po /usr/lib/perl5/site_perl/5.8.0/Locale/soko/strings.po /usr/lib/perl5/site_perl/Locale/soko/strings.po /usr/lib/perl5/5.8.8/i686-linux/Locale/Maketext/soko/strings.po /usr/lib/perl5/5.8.8/Locale/Maketext/soko/strings.po /usr/lib/perl5/site_perl/5.8.8/i686-linux/Locale/Maketext/soko/strings.po /usr/lib/perl5/site_perl/5.8.8/Locale/Maketext/soko/strings.po /usr/lib/perl5/site_perl/5.8.5/Locale/Maketext/soko/strings.po /usr/lib/perl5/site_perl/5.8.4/Locale/Maketext/soko/strings.po /usr/lib/perl5/site_perl/5.8.3/Locale/Maketext/soko/strings.po /usr/lib/perl5/site_perl/5.8.2/Locale/Maketext/soko/strings.po /usr/lib/perl5/site_perl/5.8.1/Locale/Maketext/soko/strings.po /usr/lib/perl5/site_perl/5.8.0/Locale/Maketext/soko/strings.po /usr/lib/perl5/site_perl/Locale/Maketext/soko/strings.po /usr/lib/perl5/5.8.8/i686-linux/Locale/Maketext/Lexicon/soko/strings.po /usr/lib/perl5/5.8.8/Locale/Maketext/Lexicon/soko/strings.po /usr/lib/perl5/site_perl/5.8.8/i686-linux/Locale/Maketext/Lexicon/soko/strings.po /usr/lib/perl5/site_perl/5.8.8/Locale/Maketext/Lexicon/soko/strings.po /usr/lib/perl5/site_perl/5.8.5/Locale/Maketext/Lexicon/soko/strings.po /usr/lib/perl5/site_perl/5.8.4/Locale/Maketext/Lexicon/soko/strings.po /usr/lib/perl5/site_perl/5.8.3/Locale/Maketext/Lexicon/soko/strings.po /usr/lib/perl5/site_perl/5.8.2/Locale/Maketext/Lexicon/soko/strings.po /usr/lib/perl5/site_perl/5.8.1/Locale/Maketext/Lexicon/soko/strings.po /usr/lib/perl5/site_perl/5.8.0/Locale/Maketext/Lexicon/soko/strings.po /usr/lib/perl5/site_perl/Locale/Maketext/Lexicon/soko/strings.po
これ全部 stat(2) して、「ぜぇぜぇ、がむばって探したけど無かったよ。じゃ、死にます」みたいな。いやぁ、そこまでがんばらなくていんだけどなぁ。そもそも scalar caller で $caller 定義しているのは本当にやりたいことなんだろうかとか思ったら 「scalar caller(1) でしょ?」ってのが RT に2年前に登録されてるな。まぁ、先にファイルが存在するのをチェックしないお前が悪いってことか。
まとめ: Locale-Maketext-Lexicon で Gettext でファイルを指定するまえに -e なりでそのファイルの存在を確かめましょう。DProfもいいけど strace を使うことで簡単に見つかるパフォーマンス改善ポイントもありますよという話でした。

コメントする