Giving CGI::Application internationalization (I18N)
Part 2
I should now have the knowledge I need to work my way through the Catalyst::Plugin::I18N module and figure out how they are doing it.
It's first method is 'setup', which is an extension of Catalysts own setup method. I'll look into how plugs work for CGI::App...
It seems that they also have a similar setup method.
Lets look at what the code is doing:-
Part 2
I should now have the knowledge I need to work my way through the Catalyst::Plugin::I18N module and figure out how they are doing it.
It's first method is 'setup', which is an extension of Catalysts own setup method. I'll look into how plugs work for CGI::App...
It seems that they also have a similar setup method.
Lets look at what the code is doing:-
sub setup {
my $self = shift;
$self->NEXT::setup(@_); ### calls setup from $selfs class tree as opposed to this modules class tree. I'm not sure why...
my $calldir = $self; ### !--
$calldir =~ s{::}{/}g; ###
my $file = "$calldir.pm"; ### These lines figure out the default path to your localization files folder
my $path = $INC{$file}; ###
$path =~ s{\.pm$}{/I18N}; ### --!
my $user_opts = $self->config->{ 'Plugin::I18N' }->{ maketext_options } || {}; ### Gets user defined variables for this module
local %options = ( %options, Path => $path, %$user_opts ); ### Overwrites this modules default Locale::Maketext::Simple import variables
### The following loads Locale::Maketext::Simple into the calling objects main namespace
eval <<"";
package $self;
Locale::Maketext::Simple->import( \%Catalyst\::Plugin\::I18N\::options );
### Check for errors and print debug info if wanted
if ($@) {
$self->log->error(qq/Couldn't initialize i18n "$self\::I18N", "$@"/);
}
else {
$self->log->debug(qq/Initialized i18n "$self\::I18N"/) if $self->debug;
}
}
At this point I'm failing to see how this setup routine gets called, and why it would extend the Catalyst setup routine as it's in a different namespace. I'll assume this is something that catalyst looks for and something I'll need to do in a different way. Taking a look at CGI::Application::Plugin::DBH it has an exportable method called dbh_config which is used to configure and setup the database connection. I'll create a similar method for my module. Here goes:-
package CGI::Application::Plugin::I18N;
use strict;
use warnings;
use carp;
use FindBin qw($RealBin);
require Locale::Maketext::Simple;
use vars qw ( $VERSION @ISA @EXPORT_OK $RealBin %DEFAULT_OPTIONS );
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(
i18n_config
);
$VERSION = '0.01';
%DEFAULT_OPTIONS = (
Path => "$RealBin/I18N",
Style => 'gettext',
Export => '_maketext',
Decode => 1,
Encoding => 'locale',
);
sub i18n_config {
my $self = shift;
local %DEFAULT_OPTIONS;
if ( @_ ) {
my %newoptions = @_;
my @valid_options = ("Class","Style","Export","Subclass","Decode","Encoding","Path");
foreach my $key (keys %newoptions) {
unless (grep (/^$key$/, @valid_options)) {
croak( "Invalid option: $key" );
}#unless
}#foreach
%DEFAULT_OPTIONS = (%DEFAULT_OPTIONS, %newoptions);
}#if
my $evalcode = qq~
package $self;
Locale::Maketext::Simple->import( \%CGI\::Application\::Plugin\::I18N\::DEFAULT_OPTIONS );
~;
eval $evalcode;
if ( $@ ) {
croak( qq~Couldn't initialize i18n, error "$@", code "$evalcode"~ );
}#if
}#sub
I've chosen to use the FindBin module to get the scripts path and base the default Lexicon folder on that, rather than play about with the calling packages name. I've also set a couple more of Locale::Maketext::Simple's options by default. There is some validation code to ensure that user submitted config has a valid name, although values aren't checked.
I must emphasize that at this point none of this code has been tested and is likely subject to change!
Some quick docs:-
use CGI::Application::Plugin::I18N qw(i18n_config);
Within your setup, cgiapp_init, cgiapp_prerun or specific runmode routine add the line
$self->i18n_config( %options );
%options are the same as for Locale::Maketext::Simple. If none are passed the following default are used:-
%DEFAULT_OPTIONS = (
Path => "$RealBin/I18N",
Style => 'gettext',
Export => '_maketext',
Decode => 1,
Encoding => 'locale',
);
$RealBin being the folder from which the executed cgi script is running.
For instance if you wanted to use maketext style markup in your lexicons you would use the line:-
$self->i18n_config( Style => 'maketext' );
Ok. Now that's sorted let's work through the other routines in Catalyst\::Plugin\::I18N
To be continued...
my $self = shift;
$self->NEXT::setup(@_); ### calls setup from $selfs class tree as opposed to this modules class tree. I'm not sure why...
my $calldir = $self; ### !--
$calldir =~ s{::}{/}g; ###
my $file = "$calldir.pm"; ### These lines figure out the default path to your localization files folder
my $path = $INC{$file}; ###
$path =~ s{\.pm$}{/I18N}; ### --!
my $user_opts = $self->config->{ 'Plugin::I18N' }->{ maketext_options } || {}; ### Gets user defined variables for this module
local %options = ( %options, Path => $path, %$user_opts ); ### Overwrites this modules default Locale::Maketext::Simple import variables
### The following loads Locale::Maketext::Simple into the calling objects main namespace
eval <<"";
package $self;
Locale::Maketext::Simple->import( \%Catalyst\::Plugin\::I18N\::options );
### Check for errors and print debug info if wanted
if ($@) {
$self->log->error(qq/Couldn't initialize i18n "$self\::I18N", "$@"/);
}
else {
$self->log->debug(qq/Initialized i18n "$self\::I18N"/) if $self->debug;
}
}
At this point I'm failing to see how this setup routine gets called, and why it would extend the Catalyst setup routine as it's in a different namespace. I'll assume this is something that catalyst looks for and something I'll need to do in a different way. Taking a look at CGI::Application::Plugin::DBH it has an exportable method called dbh_config which is used to configure and setup the database connection. I'll create a similar method for my module. Here goes:-
package CGI::Application::Plugin::I18N;
use strict;
use warnings;
use carp;
use FindBin qw($RealBin);
require Locale::Maketext::Simple;
use vars qw ( $VERSION @ISA @EXPORT_OK $RealBin %DEFAULT_OPTIONS );
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(
i18n_config
);
$VERSION = '0.01';
%DEFAULT_OPTIONS = (
Path => "$RealBin/I18N",
Style => 'gettext',
Export => '_maketext',
Decode => 1,
Encoding => 'locale',
);
sub i18n_config {
my $self = shift;
local %DEFAULT_OPTIONS;
if ( @_ ) {
my %newoptions = @_;
my @valid_options = ("Class","Style","Export","Subclass","Decode","Encoding","Path");
foreach my $key (keys %newoptions) {
unless (grep (/^$key$/, @valid_options)) {
croak( "Invalid option: $key" );
}#unless
}#foreach
%DEFAULT_OPTIONS = (%DEFAULT_OPTIONS, %newoptions);
}#if
my $evalcode = qq~
package $self;
Locale::Maketext::Simple->import( \%CGI\::Application\::Plugin\::I18N\::DEFAULT_OPTIONS );
~;
eval $evalcode;
if ( $@ ) {
croak( qq~Couldn't initialize i18n, error "$@", code "$evalcode"~ );
}#if
}#sub
I've chosen to use the FindBin module to get the scripts path and base the default Lexicon folder on that, rather than play about with the calling packages name. I've also set a couple more of Locale::Maketext::Simple's options by default. There is some validation code to ensure that user submitted config has a valid name, although values aren't checked.
I must emphasize that at this point none of this code has been tested and is likely subject to change!
Some quick docs:-
use CGI::Application::Plugin::I18N qw(i18n_config);
Within your setup, cgiapp_init, cgiapp_prerun or specific runmode routine add the line
$self->i18n_config( %options );
%options are the same as for Locale::Maketext::Simple. If none are passed the following default are used:-
%DEFAULT_OPTIONS = (
Path => "$RealBin/I18N",
Style => 'gettext',
Export => '_maketext',
Decode => 1,
Encoding => 'locale',
);
$RealBin being the folder from which the executed cgi script is running.
For instance if you wanted to use maketext style markup in your lexicons you would use the line:-
$self->i18n_config( Style => 'maketext' );
Ok. Now that's sorted let's work through the other routines in Catalyst\::Plugin\::I18N
To be continued...
Leave a comment