日向夏特殊応援部隊

俺様向けメモ

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フラグが立ってないので当然っちゃ当然ですが