DB が euc で画面出力が sjis というようなレガシーなウェブシステムの場合、Catalyst で構築するなら Catalyst::Plugin::Charsets::Japanese を使うと超便利。
config で指定するだけで文字コード変換ができてしまいます。
MyApp.yaml で
charsets:
in: EUC-JP
out: Shift_JIS
と設定すると Catalyst の内部では euc で扱い、output する時に自動的に sjis へ変換してくれます。
しかも、フォームから入力されたデータも Catalyst に入る時に sjis->euc 変換をしてくれます。
なので、データを DB へ保存する時も文字コード変換を意識せずに実装できて大変便利です。
でも、1点困ることがあります。
画面出力に使用する(HTML)テンプレートも(Catalystの)内部(データ)扱いとなるため、テンプレートも euc で扱われます。
もしテンプレートが sjis だと、sjis のテンプレートに(フォームやDBから取得した) euc のデータを挿入して、それを最終的に output する時に euc->sjis の変換をかけます。
従って、sjis のテンプレート部分も euc として扱われ euc->sjis 変換をするので文字が化ける(と思う)。
テンプレートが euc ならなんら問題ないのですが、でも大抵において、画面出力が sjis ならテンプレートも sjis の方が都合が良い。
META タグで content-type の charset=Shift_JIS と書いているし。
デザイナーさんも euc より sjis の方が都合が良いし。
で、どうするか。
Catalyst::Plugin::Charsets::Japanese を使う以上、一度内部で sjis->euc 変換するしかない。
(無駄な作業ではあるけれど。。。)
テンプレートエンジンでテンプレートの文字コードを変換してしまうと楽。
ボクは View に Catalyst::View::HTML::Template::Compiled を使っているので、HTML::Template::Compiled の filter 機能を利用します。
使い方は HTML::Template の filter 機能と全く同じ。
HTML::Template の perldoc に具体的な使い方が書いてあります。
これを元に、HTML::Template::Compiled でテンプレートの文字コード変換を行います。
MyApp::View::HTC で、
package MyApp::View::HTC;
use strict;
use base 'Catalyst::View::HTML::Template::Compiled';
use Jcode;
__PACKAGE__->config(
filter => \&jcode_filter,
);
sub jcode_filter {
my $text_ref = shift;
$$text_ref = Jcode->new($$text_ref, 'sjis')->euc; # sjis->euc 変換
}
1;
これで、テンプレートが処理される前に sjis->euc 変換されます。
sjis から euc に変換されたテンプレートに対して(フォームやDBから取得した) euc のデータが挿入されます。これだと内部的には全て euc です。
最終的に Catalyst::Plugin::Charsets::Japanese で euc->sjis の変換が行われて出力されます。
ちょっと不毛な感じもするけれど・・・
もっといいやり方ないかな?
(全部 UTF-8 で統一できれば良いのだけれど、それは出来ないので。。。)
