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