At our company, we have a single app available in multiple locales.  We use 
Mason, but we don't include any content in the components.  Since it's a one 
size fits all app, we keep all of our content (all UTF8) in versioned XML files 
as strings; each string having a unique string id as an XML attribute.  We have 
separate HTML templates that use HTML::Template to process the string files for 
static content substitution, as well as for dynamic data.  This way, we have 
single Mason components that get cached, and we call HTML::Template at 
run-time, to choose the proper templates from the following type of directory 
structure:

.../html/enus   (English, US)
          /engb   (Queen's English, UK)
          /svse   (Swedish, Sweden)
         etc.

Because we keep our static content in XML files, we can pre-build all HTML 
templates (all sites can share the same templates) or we can do substitution 
dynamically at run-time.  We only need to make unique templates for UI that is 
unique to a locale (i.e. registration fields, etc.).  Also, we can edit only 
the string id's in the XML files we need, and check in new versions as changes 
or additions arise.  The XML format works well with our L10n group, as their 
tools just slurp them in, and they can edit away.  Since we can dynamically 
build our templates at run-time, we can also offer special template content 
that displays string ID's for each string shown, with respect to the XML string 
file it came from; this allows the LQA folks to quickly identify incorrect 
strings in context in our app, and go directly to the proper string in their 
L10n tools to edit it.  (Of course, we pre-build the localized HTML before 
releases to production, though, better performance).  How we know w
 hich locale templates to use is based off the domain of the incoming request.  
But, the way we designed it, any user could view our site in any of the locales 
we support, at any time.

Basically, we are using HTML::Mason and HTML::Template out-of-the-box for this, 
no customization needed.  Not sure if this helps at all, but it works well for 
us.  My $0.02 ...
- Jeff


----- Original Message ----
From: John Williams <[EMAIL PROTECTED]>
To: Kovacs Baldvin <[EMAIL PROTECTED]>
Cc: mason-users@lists.sourceforge.net
Sent: Tuesday, January 9, 2007 9:53:41 AM
Subject: Re: [Mason] l10n efficiency

On Tue, 9 Jan 2007, Kovacs Baldvin wrote:
> I am wondering if a different approach would be possible: why don't we
> hack the mason compiler to compile not just .obj files from the
> templates, but .en.obj, .fr.obj, .de.obj, ... When a component is to be
> run, then the appropriate .obj file is taken, and would run the same
> speed as there were no internationalization would be in place.

The way I do it is to override Mason's Resolver class.  The language is
part of the URL, and my Resolver actually reads the html file from a
common directory.  This way there is only one copy of the untranslated
mason source, but the mason cache has one copy for each language.

We use <trans key=xyzzy> tags to delimit the translatable text.  Mason's
"<% %>" tags are replaced by "{1}" in the translation database, so they
can be reordered.  (In my experience, even that much flexibility confuses
many contractual translators.)

I cannot share my company's translation code, but here is the get_info
function from our Resolver subclass.  It just a modified version
of the code from HTML::Mason::Resolver::File.  Modifying this use to
Maketext is left as an exercise for the reader.

sub get_info {
        my ($self, $path) = @_;

        # get the language handle
        my $tr = TNI::Translation->new(
                comp_root => $self->comp_root,
                path => $path,
        );
    # language is determined from the URL
        my $language = $tr->language;
    # when the translation database was last modified
        my $modified = $tr->domain_modified( unix=>1 ) || 0;

    # find the untranslated file
        my $english = $path;
        $english =~ s{//+}{/}g;
        $english =~ s{^/([^/]*?)/\Q$language\E/}{/default/english/} if 
$language;

        foreach my $pair ($self->comp_root_array) {
                my $fname = File::Spec->canonpath( File::Spec->catfile( 
$pair->[1], $path ) );
                my $srcfile = File::Spec->canonpath( File::Spec->catfile( 
$pair->[1], $english ) );

                next unless -f $srcfile;
                my $filemodified = (stat _)[9];
                $modified = $filemodified if $filemodified > $modified;

                my $key = $pair->[0];
                my $base = $key eq 'MAIN' ? '' : "/$key";
                $key = undef if $key eq 'MAIN';

                return
                        HTML::Mason::ComponentSource->new
                                        ( friendly_name => $fname,
                                          comp_id => "$base$path",
                                          last_modified => $modified,
                                          comp_path => $path,
                                          comp_class => 
'HTML::Mason::Component::FileBased',
                                          extra => { comp_root => $key },
                                          #source_callback => sub { 
read_file_ref($srcfile) },
                                          source_callback => sub {
# read the source file and translate
TNI::Translation::Parse::HTML->new( tr=>$tr 
)->translate_page_ref(read_file_ref($srcfile));
                      },
                                        );
        }

        # see if path corresponds to real filesystem path, a common new user 
mistake
        my $fs_path = File::Spec->catfile( split /\//, $path );
        if ( defined $fs_path && -e $fs_path )
        {
                warn "Your component path ($path) matches a real file on disk 
($fs_path).  Have you read about the component root in the Administrator's 
Manual (HTML::Mason::Admin)?";
        }

        return;
}





-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Mason-users mailing list
Mason-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mason-users




-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Mason-users mailing list
Mason-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mason-users

Reply via email to