catalyst.perl.kmtz.net RSSフィード

 | 

2007-05-19動的に文字コードを変更して出力する Catalyst::Plugin::Unicode::Encoding このエントリーを含むブックマーク

リクエスト毎に出力の文字コードを変換するプラグインCatalyst::Plugin::Unicode::Encoding を元に作成してみた。下の例だと、shiftjis と utf8 のみに対応するが、$c->config から読み込むようにも簡単に変更可能。

package Catalyst::Plugin::Private::Unicode::Encoding;

use strict;
use warnings;
use Encode 2.10 ();
use Encode::Guess qw(utf8 shiftjis);

our $VERSION = 0.01;
our $CHECK   = Encode::FB_CROAK | Encode::LEAVE_SRC;

sub finalize {
    my $c = shift;

    unless ( $c->res->body ) {
        return $c->NEXT::finalize;
    }

    unless ( $c->res->content_type =~ /^text|xml$|javascript$/ ) {
        return $c->NEXT::finalize;
    }

    unless ( Encode::is_utf8( $c->res->body ) ) {
        return $c->NEXT::finalize;
    }

    unless ( ref $c->stash->{'encoding'} ) {
        unless ( $c->stash->{'encoding'} =
            Encode::find_encoding( $c->stash->{'encoding'} ) )
        {
            $c->stash->{'encoding'} = Encode::find_encoding('utf8');
        }
        $c->log->debug( 'changed:' . $c->stash->{'encoding'}->mime_name );
    }
    $c->log->debug( 'out:' . $c->stash->{'encoding'}->mime_name );
    $c->res->body( $c->stash->{'encoding'}->encode( $c->res->body, $CHECK ) );

    $c->NEXT::finalize;
}

sub prepare_parameters {
    my $c = shift;

    $c->NEXT::prepare_parameters;

    my $str;
    for my $value ( values %{ $c->req->params } ) {
        $str .= $_ for ( ref($value) ? @{$value} : $value );
    }
    my $decoder;
    if ($str) {
        eval {
            $decoder =
              Encode::Guess->guess_encoding( $str, qw(utf8 shiftjis) );
        };
        $decoder = Encode::find_encoding('utf8') unless ($decoder);
        for my $value ( values %{ $c->req->params } ) {
            next
              if ( ref $value && ref $value ne 'ARRAY' );
            for ( ref($value) ? @{$value} : $value ) {
                $_ = $decoder->decode( $_, $CHECK );
            }
        }
    }
    else {
        $decoder = Encode::find_encoding('utf8');
    }
    $c->stash->{'encoding'} = $decoder;
    $c->log->debug( 'in:' . $c->stash->{'encoding'}->mime_name );
}

1;

__END__

コントローラの中で、

$c->stash->{'encoding'} = 'shiftjis';
# or
$c->stash->{'encoding'} = 'utf8';

のように指定するとその文字コードで出力する。テンプレートは全て utf8 で記述することを想定。ちなみに、使用される文字コードルールは下のような感じ。

1.リクエスト時にフォーム等でパラメータが渡されている場合は、パラメータ文字コード自動判別して utf8 に変換してからコントローラに渡す。(コントローラでは従来どおり $c->req->param でアクセス

2.レスポンスの内容を utf8 から指定の文字コードに変換して出力する。文字コード$c->stash->{'encoding'} で指定されていればそれを使い、なければ1の処理に使った文字コードを使用し、1の際にパラメータがなく判別されなかった場合には utf8 が使用される。

 |