Skip Menu |

This queue is for tickets about the Catalyst-Plugin-I18N CPAN distribution.

Report information
The Basics
Id: 25050
Status: resolved
Priority: 0/
Queue: Catalyst-Plugin-I18N

People
Owner: bobtfish [...] bobtfish.net
Requestors: chris+rt [...] chrisdolan.net
Cc:
AdminCc:

Bug Information
Severity: Unimportant
Broken in: 0.05
Fixed in: (no value)



Subject: [PATCH] configurability enhancements
Attached is a patch that implements a 100% backward-compatible overhaul of I18N.pm to allow much greater configurability. This patch allows the developer to override any Locale::Maketext::Simple parameter, if needed. I found this necessary to get the encoding to work right with Template-Toolkit for my auto-generated Locale::Maketext lexicons (i.e. passing 'Decode => 0'). This patch also adds the additional feature of reporting the languages of all the lexicons that are installed. This facilitates, say, writing pulldowns for language selection in HTML. I know you folks prefer that patches like this be proposed on the mailing list instead of in RT, but it's just too time consuming to follow the Catalyst lists...
Subject: i18n.patch
--- /Users/chris/Work/catalyst/Catalyst-Plugin-I18N/I18N.pm 2006-12-06 13:53:17.000000000 -0600 +++ inc/Catalyst/Plugin/I18N/Configurable.pm 2007-02-20 09:25:38.000000000 -0600 @@ -1,21 +1,24 @@ -package Catalyst::Plugin::I18N; +package Catalyst::Plugin::I18N::Configurable; +use warnings; use strict; use NEXT; use I18N::LangTags (); use I18N::LangTags::Detect; +use File::Spec; +# Don't "use" because we want to delay import() require Locale::Maketext::Simple; -our $VERSION = '0.05'; +our $VERSION = '0.01'; =head1 NAME -Catalyst::Plugin::I18N - I18N for Catalyst +Catalyst::Plugin::I18N::Configurable - I18N for Catalyst =head1 SYNOPSIS - use Catalyst 'I18N'; + use Catalyst 'I18N::Configurable'; print join ' ', @{ $c->languages }; $c->languages( ['de'] ); @@ -50,27 +53,111 @@ =head3 setup +Figure out where the I18N C<.po> or C<.pm> files are located (by +default: F<lib/MyApp/I18N/>) Initialize Locale::Maketext::Simple. +Collect a list of which languages have I18N files present. + +Configuration options -- all of these can be set like this example: + + MyApp->config(i18n => { + dir => '/usr/share/MyApp/localization', + locale_maketext_simple_opts => { + Style => 'gettext', + Decode => 0, + }, + }); + +=over + +=item pkg => $class + +The parent class of your I18N namespace. Defaults to the package of +your Catalyst app (e.g. C<MyApp>). + +=item subpkg => $subdir + +The directory under your app which contains the localization files. +Defaults to C<I18N>. + +=item dir => $dir + +The path to a directory which contains the localization files. If +this is set, the C<subpkg> is ignored. By default, it is +C<lib/$pkg/$subpkg/>. + +=item locale_maketext_simple_opts => $hashref + +Defaults to: + + { Path => $dir, Style => 'maketext', Decode => 1, + Class => $pkg, Subclass => $subpkg } + +=back + =cut sub setup { my $self = shift; $self->NEXT::setup(@_); - my $calldir = $self; - $calldir =~ s#::#/#g; - my $file = "$calldir.pm"; - my $path = $INC{$file}; - $path =~ s#\.pm$#/I18N#; - eval <<""; - package $self; - import Locale::Maketext::Simple Path => '$path', Export => '_loc', Decode => 1; + $self->config->{i18n} ||= {}; + + my $pkg = $self->config->{i18n}->{pkg} ||= $self; + my $subpkg = $self->config->{i18n}->{subpkg} ||= 'I18N'; - if ($@) { - $self->log->error(qq/Couldn't initialize i18n "$self\::I18N", "$@"/); + my $i18n_dir = $self->config->{i18n}->{dir}; + if (!$i18n_dir) { + # This is deliberately a Unix path for simplicity + # Locale::Maketext::Simple remaps to local path + (my $app_pm = "$pkg.pm") =~ s{::}{/}gxms; + (my $app_dir = $INC{$app_pm}) =~ s{\.pm\z}{}xms; + $i18n_dir = File::Spec->catdir($app_dir, $subpkg); + $self->config->{i18n}->{dir} = $i18n_dir; } - else { - $self->log->debug(qq/Initialized i18n "$self\::I18N"/) if $self->debug; + if (! File::Spec->file_name_is_absolute($i18n_dir)) { + $i18n_dir = $self->path_to($i18n_dir)->stringify; + } + + my %default_opts = ( + Path => $i18n_dir, + Style => 'maketext', + Decode => 1, + Class => $pkg, + Subclass => $subpkg, + ); + my %opts = ( + %default_opts, + %{ $self->config->{i18n}->{locale_maketext_simple_opts} || {} }, + ); + + Locale::Maketext::Simple->reload_loc(); + my ($loc, $loc_lang) = Locale::Maketext::Simple->load_loc(%opts); + { + # Manual export to avoid another eval + no strict 'refs'; ## no critic(Strict) + *{$pkg . '::_loc'} = $loc || Locale::Maketext::Simple->default_loc(%opts); + *{$pkg . '::_loc_lang'} = $loc_lang || sub { 1 }; } + $self->log->debug(qq/Initialized i18n "$pkg\::$subpkg"/) if $self->debug; + + if (! $self->config->{i18n}->{installed_languages}) { + my %langs; + if (opendir my $dir_fh, $i18n_dir) { + # Pull root of valid filenames + for my $entry (readdir $dir_fh) { + my ($lang) = $entry =~ m/\A (\w+)\.(?:pm|po|mo) \z/xms; + next if !$lang; + next if $lang eq 'i_default'; + $lang =~ s/_/-/gxms; + $langs{$lang} = 1; + } + closedir $dir_fh; + } + + $self->config->{i18n}->{installed_languages} = [ sort keys %langs ]; + } + + return; } =head2 METHODS @@ -97,8 +184,8 @@ 'i-default' ]; } - no strict 'refs'; - &{ ref($c) . '::_loc_lang' }( @{ $c->{languages} } ); + no strict 'refs'; ## no critic(Strict) + &{ $c->config->{i18n}->{pkg} . '::_loc_lang' }( @{ $c->{languages} } ); return $c->{languages}; } @@ -110,10 +197,11 @@ sub language { my $c = shift; - my $class = ref $c || $c; - my $lang = ref "$class\::I18N"->get_handle( @{ $c->languages } ); - $lang =~ s/.*:://; + my $pkg = $c->config->{i18n}->{pkg}; + my $subpkg = $c->config->{i18n}->{subpkg}; + my $lang = ref "$pkg\::$subpkg"->get_handle( @{ $c->languages } ); + $lang =~ s/.*:://xms; return $lang; } @@ -133,10 +221,27 @@ sub localize { my $c = shift; $c->languages; - no strict 'refs'; - return &{ ref($c) . '::_loc' }( $_[0], @{ $_[1] } ) + no strict 'refs'; ## no critic(Strict) + return &{ $c->config->{i18n}->{pkg} . '::_loc' }( $_[0], @{ $_[1] } ) if ( ref $_[1] eq 'ARRAY' ); - return &{ ref($c) . '::_loc' }(@_); + return &{ $c->config->{i18n}->{pkg} . '::_loc' }(@_); +} + +=head3 supported_languages + +Returns the list of languages for which there are localizations. + +=cut + +sub supported_languages { + my ( $c, $languages ) = @_; + + if ($languages) { + $c->{supported_languages} = $languages; + } elsif (!$c->{supported_languages}) { + $c->{supported_languages} ||= $c->config->{i18n}->{installed_languages}; + } + return $c->{supported_languages}; } =head1 SEE ALSO @@ -150,6 +255,8 @@ Brian Cassidy, C<bricas@cpan.org> Christian Hansen, C<chansen@cpan.org> + +Chris Dolan, C<cdolan@cpan.org> =head1 COPYRIGHT
On Tue Feb 20 10:36:37 2007, CDOLAN wrote: Show quoted text
> Attached is a patch that implements a 100% backward-compatible overhaul > of I18N.pm to allow much greater configurability. This patch allows the > developer to override any Locale::Maketext::Simple parameter, if needed. > I found this necessary to get the encoding to work right with > Template-Toolkit for my auto-generated Locale::Maketext lexicons (i.e. > passing 'Decode => 0').
This bug has been partially work on due to RT #32132. Catalyst::Plugin::I18N 0.07 should allow you to specify any Locale::Maketext::Simple option thusly: __PACKAGE__->config( 'Plugin::I18N' => { maketext_options => { Decode => 0 } } ); The "supported_languages" feature of your patch has yet to be looked at in any great detail. -Brian
Subject: installed_languages list
I had implemented a similar feature to support_languages as languages_list. However, it my usage of it, more languages than I was expecting were appearing. So I've changed SVN so that it now uses Chris' technique of reading the I18N/ directory to gather the list of available languages. I've also changed the call to be "installed_languages" which makes more sense. Is it possible to do a release with these changes?
Yes. Released as 0.10.