Hatena::ブログ(Diary)

Yet Another Hackadelic

2008-01-22 程度の低いと思う人にマジレスする奴はその人と同じ程度と言う法則

Template-Toolkitでマルチバイトな話

先に言っておくと、hide-kさんのまとめが分かりやすいです。

最もCatalystを使う際にと言う事ですが。

utf8フラグを立てないでTTを使う場合

ソース自身はutf8で書くんですけど、

#!/usr/bin/perl

use strict;
use warnings;

use Carp::Clan;
use Path::Class;

use Template;

my $base_dir = dir($ENV{HOME}, qw/tmp tt_test/);

my $template = Template->new({
    COMPILE_DIR => $base_dir->subdir('tt.cache')->stringify,
    COMPILE_EXT => 'c',
});

my $output = '';
my $vars = {
    id => 'ZIGOROu',
    name => 'ますだ じごろう'
};

$template->process(\*DATA, $vars, \$output) || carp $template->error;

print $output;

__DATA__
[% id %]
[% name %]
[% name | truncate(7) %]

こうすると指定したディレクトリにtt.cacheってディレクトリが出来て、コンパイル済みのファイルが出来ます。

が、やってみると分かりますが、truncateの出力で悲しい目に遭います。*1

utf8フラグを立てる場合

こんな感じ。

#!/usr/bin/perl

use strict;
use warnings;

use Carp::Clan;
use Path::Class;

use Template;
use Template::Provider::Encoding;
use Template::Stash::ForceUTF8;

my $base_dir = dir($ENV{HOME}, qw/tmp tt_test/);

my $template = Template->new({
    LOAD_TEMPLATES => [ Template::Provider::Encoding->new({
        COMPILE_DIR => $base_dir->subdir('tt.cache')->stringify,
        COMPILE_EXT => 'c',
    }) ],
    STASH => Template::Stash::ForceUTF8->new,
});

my $output = '';
my $vars = {
    id => 'ZIGOROu',
    name => "ますだ じごろう"
};

$template->process(\*DATA, $vars, \$output) || carp $template->error();
utf8::encode($output);

print $output;

__DATA__
[% id %]
[% name %]
[% name | truncate(7) %]

ほとんど変わらないんですが、

を使ってるって事が大きく違います。

前者は渡した変数をテンプレート内部でutf8フラグを強制的に立ててくれる物で、後者はテンプレートそのものを指定したencodingでutf8フラグを立ててしまうという物です。

あとはこのようにTemplate::Providerの子孫クラスをnewしてLOAD_TEMPLATESに渡すので、事前にProviderに必要なconfigをProvider自体に渡しておかないとトラブルがおきます。

例としては、

  • 通したはずのINCLUDE_PATHからテンプレートファイルが見つからない
  • COMPILEされるはずがされない

などなど。

詳しいオプションは、

を見て下さい。

まとめ

TTの枠組みくらい理解しておかないとダメだなと思った><

実践あるのみですね。

*1:ここはutf8フラグが立ってないので当然っちゃ当然ですが