Template-Multilingual-1.00/0000755000076500000240000000000011134666573014472 5ustar ericstaffTemplate-Multilingual-1.00/Build.PL0000444000076500000240000000072111134666573015764 0ustar ericstaffuse strict; use warnings; use Module::Build; my $builder = Module::Build->new( module_name => 'Template::Multilingual', license => 'perl', dist_author => 'Eric Cholet ', dist_version_from => 'lib/Template/Multilingual.pm', requires => { 'Test::More' => 0, 'Template' => 2, }, add_to_cleanup => [ 'Template-Multilingual-*' ], ); $builder->create_build_script(); Template-Multilingual-1.00/Changes0000444000076500000240000000237511134666573015772 0ustar ericstaffRevision history for Template-Multilingual 1.00 2009-01-18 add support for language subtags, e.g. en_US or en-US Language codes are now matched by [^<>]+ (previously \w+) 0.09 2006-07-30 remove Test::Pod and Test::Pod::Coverage tests 0.08 2006-11-29 fix incorrect doc 0.07 2006-08-26 remove Module::Signature support, does more harm than good 0.06 2005-10-31 add support for TAG_STYLE, START_TAG and END_TAG template options, thanks to Birgit Kellner for pointing this out. Template::Multilingual::Parser::sections() is now correctly documented 0.05 2005-06-17 more robust parsing; text within ... but outside any .. is now ignored add Test::Pod and Test::Pod::Coverage tests improve Template::Multilingual::Parser documentation 0.04 2005-05-06 add GPG signature using Module::Signature 0.03 2005-05-18 LANGUAGE_VAR option selects name of language template variable 0.02 2005-04-11 Language codes are now matched by <\w+> (previously <[a-z]{2}>) Improve test coverage Fix/improve pod 0.01 2005-04-10 First version, released on an unsuspecting world. Template-Multilingual-1.00/lib/0000755000076500000240000000000011134666573015240 5ustar ericstaffTemplate-Multilingual-1.00/lib/Template/0000755000076500000240000000000011134666573017013 5ustar ericstaffTemplate-Multilingual-1.00/lib/Template/Multilingual/0000755000076500000240000000000011134666573021461 5ustar ericstaffTemplate-Multilingual-1.00/lib/Template/Multilingual/Parser.pm0000444000076500000240000001712611134666573023260 0ustar ericstaffpackage Template::Multilingual::Parser; use strict; use base qw(Template::Parser); our $VERSION = '1.00'; sub new { my ($class, $options) = @_; my $self = $class->SUPER::new($options); $self->{_sections} = []; $self->{_langvar} = $options->{LANGUAGE_VAR} || 'language'; my $style = $self->{ STYLE }->[-1]; @$self{ qw(_start _end) } = @$style{ qw( START_TAG END_TAG ) }; for (qw( _start _end )) { $self->{$_} =~ s/\\([^\\])/$1/g; } return $self; } sub parse { my ($self, $text) = @_; # isolate multilingual sections $self->_tokenize($text); # replace multilingual sections with TT directives my ($S, $E, $LANGVAR) = map $self->{$_}, qw(_start _end _langvar); # if language is a variant (en_US), create a template variable holding the fallback value (en) $text = "$S IF (tm_matches = $LANGVAR.match('^(\\w+)[-_].*\$')); tm_fb = tm_matches.0; END $E"; for my $section (@{$self->{_sections}}) { if ($section->{nolang}) { $text .= $section->{nolang}; } elsif (my $t = $section->{lang}) { my @languages = keys %$t; # first loop through languages: look for exact match $text .= "$S tm_f = 0; SWITCH $LANGVAR $E"; for my $lang (@languages) { $text .= "$S CASE '$lang' $E" . $t->{$lang}; } # add a default case to trigger fallback $text .= "$S CASE; tm_f=1; END; $E"; # second loop: fallback to primary language (en_US matches en) $text .= "$S IF tm_fb AND tm_f; tm_f=0; SWITCH tm_fb; $E"; for my $lang (@languages) { $text .= "$S CASE '$lang' $E" . $t->{$lang}; } # add a default case to trigger last resort fallback # LANG is fr_XX or fr but template has neither # we try to fallback to fr_YY is present my %seen; my @fallbacks = map { /^(\w+)[-_].*$/ && !$seen{$_}++ ? [ $1 => $_] : () } sort @languages; if (@fallbacks) { # third loop: fallback to first available variant $text .= "$S CASE; tm_f=1; END; END; IF tm_f; SWITCH tm_fb || $LANGVAR; $E"; for my $ref (@fallbacks) { my ($lang, $variant) = @$ref; $text .= "$S CASE '$lang' $E" . $t->{$variant}; } } $text .= "$S END; END $E"; } } return $self->SUPER::parse ($text); } sub _tokenize { my ($self, $text) = @_; # extract all sections from the text $self->{_sections} = []; my @tokens = split m!(.*?)!s, $text; my $i = 0; for my $t (@tokens) { if ($i) { # ... multilingual section my %section; while ($t =~ m!<([^<>]+)>(.*?)!gs) { $section{$1} = $2; } push @{$self->{_sections}}, { lang => \%section } if %section; } else { # bare text push @{$self->{_sections}}, { nolang => $t } if $t; } $i = 1 - $i; } } sub sections { $_[0]->{_sections} } =head1 NAME Template::Multilingual::Parser - Multilingual template parser =head1 SYNOPSIS use Template; use Template::Multilingual::Parser; my $parser = Template::Multilingual::Parser->new(); my $template = Template->new(PARSER => $parser); $template->process('example.ttml', { language => 'en'}); =head1 DESCRIPTION This subclass of Template Toolkit's C parses multilingual templates: templates that contain text in several languages. Hello! Bonjour ! Use this module directly if you have subclassed C