morgon has asked for the wisdom of the Perl Monks concerning the following question:

Hi!

I work on a web-application that needs to generate XML in different encodings (utf-8 and iso8859-15), depending on the client.

I would like to generate the XML with TT, ideally with one shared template for both cases. (The problem is getting the interpolated variables encoded properly).

I have tried something like this:

use strict; use Template; my $config = { ENCODING => "iso8859-15", }; my $template = Template->new($config); $template->process("test.tt", { var => "gödel" });
But it does not come out right - it comes out as utf8.

Can someone help me here?

The system is Ubuntu Server 10.04 with Perl 5.10.

Replies are listed 'Best First'.
Re: Template Toolkit and different encodings
by ikegami (Patriarch) on Dec 23, 2010 at 00:57 UTC

    You appears to inventing configuration options. Template::Manual::Config makes no mention of an ENCODING configuration option. (Upd: There's an ENCODING configuration option for Template::Provider, but it only affects decoding. )

    Template Toolkit doesn't appear to do any encoding. No problem, that gives you greater flexibility. Just do the encoding yourself.

    binmode STDOUT, ":encoding(UTF-8)";
Re: Template Toolkit and different encodings
by graff (Chancellor) on Dec 23, 2010 at 04:52 UTC
    Just to clarify a bit on what ikegami said above (and just to prove it for myself), here's a little test script to demonstrate a run-time choice of output encoding. When you run this on the command line with no args, the output will be iso-8859-15; when you add "utf8" as an option, that will be the output encoding. The template is the same in both cases.
    #!/usr/bin/perl use strict; use warnings; use Template; use Encode; my $encoding = 'iso-8859-15'; my @testchars = map { encode( $encoding, chr( $_ )) } ( 0xc0 .. 0xff ) +; if ( @ARGV and $ARGV[0] eq 'utf8' ) { $_ = decode( $encoding, $_ ) for ( @testchars ); $encoding = 'utf8'; } my $tmpfile = "test.$$.tt"; open( TMP, ">", "/tmp/$tmpfile" ) or die "/tmp/$tmpfile: $!"; print TMP while (<DATA>); close TMP; binmode STDOUT, "encoding($encoding)"; my $tt = Template->new( INCLUDE_PATH => "/tmp" ) or die "template init. error\n"; $tt->process( $tmpfile, { enc => $encoding, testchars => \@testchars } + ) or die "template proc. error\n"; __DATA__ <html> <p>This page should be using [% enc %].</p> <table> [% FOREACH i IN [ 0 .. 3 ] -%] <tr> [% FOREACH j IN [ 0 .. 15 ] %] [%- k = i * 16 + j -%] <td>[% testchars.$k %]</td> [% END -%] </tr> [% END -%] </table> </html>
      Thanks a lot for your feedback.

      One thing thougth:

      I will use TT via CGI::Application::Plugin::TT running under mod_perl.

      Does that change anything?

        I will use TT via CGI::Application::Plugin::TT

        That's how I normally use TT as well. (I had to go back to the manual to see about running it by itself.)

        Does that change anything?

        No -- just make sure that STDOUT is set to the same encoding as the template string variables, as shown in the example; then use the plugin syntax in the normal way to invoke the TT "process" function.

        If you're sending HTML to a client, you might want to look up how CGI::Application manages the MIME header that precedes the <html> tag, so that the client (browser) knows what encoding to use. But if you're sending XML, then starting the template like this should suffice:

        <?xml version="1.0" encoding="[% enc %]" ?>