Thread: Re: [htmltmpl] language support
Brought to you by:
samtregar
From: Carl F. <C.A...@du...> - 2004-08-24 11:25:59
|
An alternative that I use: In the template file, use a simple VAR tag, <TMPL_VAR name="hello"> Store all the different language's text in a database or text files. In the CGI, load the appropriate language based on input parameters or cookie value, my $lang = $cgi->param('lang') || 'en'; my $gui = load_gui ($lang); Then load the text into the template, $tmpl->param (hello => $gui->{hello}); You'll obviously have to write the load_gui sub yourself, depending on how you store the data. Carl >>> Martin Sarfy <sa...@ic...> 24/08/2004 12:09:41 >>> Hi folks, I lack multiple language support in HTML::Template. My idea is that I wrote complete HTML page with tons of design included and then wrap pieces of text using e.g. <TMPL_LANG lang="eng">Hello</TMPL_LANG> <TMPL_LANG lang="spa">Ciao</TMPL_LANG> <TMPL_LANG lang="cze">Ahoj</TMPL_LANG> How do you solve this problem? Using <TMPL_IF lang=""> construct isn't appropriate for several reasons: -- $lang is not accessible in <TMPL_LOOP> context -- it's too clumsy for manual writting -- <TMPL_IF> is not 'system' solution, it cannot handle e.g. substitution of similar languages or so. Creating another copy of template file with translation is not maintainable because of changes in design. Or should I use GNU gettext in some way? Thanks a lot for advice -- Martin Sarfy ------------------------------------------------------- SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media 100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33 Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift. http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285 _______________________________________________ Html-template-users mailing list Htm...@li... https://lists.sourceforge.net/lists/listinfo/html-template-users |
From: Mark A. F. <mar...@ea...> - 2004-08-24 17:44:15
|
From: Sam Tregar <sa...@tr...> >> -- it's too clumsy for manual writting > >I don't understand what you mean by this. If you consider >HTML::Template's syntax to be too clumsy then why are you using it? I understand what he's saying. When initially facing the chore of international language support, it's perplexing how to balance between language specific templates, replaceable text, and some replaceable text which is pull-down values you'd more naturally consider to be part of the template. I remember I went through this same discussion on this forum a year ago. I eventually chose to: 1. Create templates within a directory structure reflecting language differences (/en, /es, etc.). The templates will contain absolutely static text (such as the title of the page, headings, etc.). 2. Create MySQL tables for form option/select lists. The columns are identified by a numeric identifier. They are grouped by a key named "language." Therefore, using the user's language and choice-number, the text to be displayed in the option/select list can be retrieved (and/or set to "selected.") A select and a template "LOOP" populates the option/select lists before display. I chose to put option/select list text (identified by number within language) in tables because they tended to be relational to the user's transactions. For example, if "blue" (or "azul" in Spanish), which are both code "1" in the color table, are attributes of the color of a product that they purchase, then "1" is stored as part of the purchase in the "purchase" table's "color" column. I can join purchase to "color" to get the color. The text of the color is just a matter of which language is in use. For me, reviewing customer orders, it would be "en". But, for customers it would be their language preference as stored in their profile. To me, this made more sense because of the relational traits. If I had the pull-down lists hard-coded in each language specific template, it would not be available to master records in the database. 3. For everything else (not static and not option/select) I used the Perl Locale::Maketext module. [1] It is similar to "gettext" but more flexible. An article [2] describes why this is important. Things like error messages and month names go into the Maketext language files. Using those three divisions of language (templates for static text, tables for relational text, Maktext for dynamic text), all I have to do is determine the visitor's language upon initial entry into the system. I use that language code to load the template (from the correct directory), select option/select values from the correct rows, and translate dynamic values using the correct Maketext "language handle." The visitor's language can be stored with their profile which is obtained using their last session-id (contained in a cookie). Or, if there is no cookie, the Perl tool I18N::AcceptLanguage [3] is helpful to guess a default for the visitor. For me, this seeemed like the best way to balance different kinds of text without excessively using tables. Or, excessively duplicating information in templates. Hope this helps. [1] http://search.cpan.org/~sburke/Locale-Maketext-1.09/lib/Locale/Maketext.pod [2] http://search.cpan.org/~sburke/Locale-Maketext-1.09/lib/Locale/Maketext/TPJ13.pod [3] http://search.cpan.org/~cgilmore/I18N-AcceptLanguage-1.02/ |
From: Alex K. <ka...@ra...> - 2004-08-24 18:20:12
|
Mark, first of all, thank you for a wonderful piece of expirience! Your way of separating things definitely worth attention. I'm going to try it for my next i18n-enabled project. One little thing I'd like to mention. Let us all use full locale names instead of ISO language codes. de_DE.ISO8859-1 or en_US.ASCII may seem a little too verbose, but in addition to language code they contain country code (which may or may not be useful) and charset name (which is VERY useful). So that one could create and use, e.g. both ru_RU.KOI8-R and ru_RU.CP1251 set of internationalized items. Alas, the world is more complex with CJK encodings and customers over there will appreciate it even more than russians. * Mark A. Fuller <mar...@ea...> [August 24 2004, 21:43]: > I understand what he's saying. When initially facing the chore of > international language support, it's perplexing how to balance > between language specific templates, replaceable text, and some > replaceable text which is pull-down values you'd more naturally > consider to be part of the template. [skip] -- Alex Kapranoff. |
From: Frederic H. <fre...@hu...> - 2004-08-24 19:44:53
|
Here's the solution I applied to this program in a project of mine. In my templates, I prefix my tokens with lang_. e.g.: <TMPL_VAR lang_address>, <TMPL_VAR lang_real_name>, etc... Then, I overloaded HTML::Template and used my own new method to which, on top of the usual HTML::Template parameters, I pass the language I want to use. In there, I loop through each template parameter, and if it starts with lang_, I look up the proper value in a dictionary system of my own. I also use the same functionality for capitalizing tokens. In that case, I suffix the tokens with _caps. That way, I can have only one template, and the graphic people can't really mess it up :) Hope that helps, Fred Hurtubise -----Message d'origine----- I can't imagine how to use it, how to enclose string in template file and how to call gettext() function (this has to be called from within HTML::Template code). I think ability to write templates in several languages is common requirement, so common that built-in support in templating engine should be considered. |
From: Cees H. <ce...@si...> - 2004-08-30 04:03:30
|
Markus Spring wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Martin Sarfy wrote: > | Hi folks, > | > | I lack multiple language support in HTML::Template. ..SNIP.. > 3 is done by subclassing HTML::Template to recognize filter arguments as > a part > of the cache key (idea and code from Cees Hek), so that localization of the > templates is done once before caching. Hi Markus, Since Sam has now pulled out the cache key generation into it's own function, much of the patch that I wrote 2 years ago is no longer really needed. You can override the _cache_key in your subclass and have it include the filter args in the generation of the cache key. The only part that would still be needed is the filter args support (which was a very small part of the patch). For those interested in the thread discussing this stuff: http://www.mail-archive.com/htm...@li.../msg00661.html Mind you that was over 2 years ago, so I wouldn't recommend using that patch since it is against 2.5 (or 2.4, I can't remember). Adding the filter ags support would be trivial to 2.7 with the availability of the new _cache_key method. > If there is interest for this solution, I could pack up the code but it > might > take some days as I am in holidays. I no longer need support for this, but feel free to strip the old patch and make it work with 2.7. It should be much simpler, and maybe a worthwhile addition to HTML::Template in the next version. Cheers, Cees ps I originally sent this earlier today, but from the wrong account, so the original message is sitting in the moderator queue. Not knowing how long it will sit there, I thought I would resend it. Hopefully the duplicate will be denied by the moderator. |
From: <swp...@sn...> - 2004-10-29 11:04:47
|
Martin Sarfy wrote: > <TMPL_LANG lang=3D"eng">Hello</TMPL_LANG> > <TMPL_LANG lang=3D"spa">Ciao</TMPL_LANG> > <TMPL_LANG lang=3D"cze">Ahoj</TMPL_LANG> The biggest problem with this, I find, is that if I use that solution the template now needs to contain all the messages in all the languages right there in the template. An update nightmare and quite messy. Here is another suggestion: I use gettext, and so I've created this filter: my $gettextFilterSub =3D sub { my ($text_ref) =3D @_; $$text_ref =3D~ s/<gettext\(\"([^\"]*)\"\)>/gettext($1)/ge; # To satisify xgettext: " }; And then: $template =3D HTML::Template->new(filename =3D> $tFile, filter =3D> $gettextFilterSub) Now, I can just type strings that are subject to translation directly in=20 the template like: <h1><gettext("My Project Title")></h1> <gettext("Hello World")> Using exactly the /<gettext\(\"([^\"]*)\"\)>/ format makes it possible to use xgettext to extract the strings that need translation: xgettext --c++ -o template.po template.tmpl Now template.po contains entries for "My Project Title" and "Hello World" that the translator can go right ahead and translate in a separate file (completely standard GNU gettext and perl Locale::gettext stuff ). If the translation is present it is used, otherwise the English (or whatever) text is used. I don't yet know how this works with caching, but I trust there is some solution to that too... Cross that bridge when I get there... :-D (I've just joined the mailing list and so I hope this ends up in the right thread...) Peter P.S.: The magic I needed to get gettext to work was: ... # Or whatever language you like - We're in Denmark here... $ENV{LANG} =3D "da_DK"; # I have a /tmp/da/LC_MESSAGES/proj.mo - created from .po with msgfmt bindtextdomain("proj","/tmp"); # We can set the codeset explicitly or do so in a round-about way # using the LC_CTYPE... # setlocale(LC_CTYPE,""); bind_textdomain_codeset("proj", "ISO-8859-1"); setlocale(LC_MESSAGES, ""); textdomain("proj"); ... --=20 Peter Valdemar M=F8rch http://www.morch.com |
From: Sam T. <sa...@tr...> - 2004-10-29 15:56:59
|
On Fri, 29 Oct 2004, Peter Valdemar M=F8rch wrote: > I use gettext, and so I've created this filter: >=20 > my $gettextFilterSub =3D sub { > my ($text_ref) =3D @_; > $$text_ref =3D~ > s/<gettext\(\"([^\"]*)\"\)>/gettext($1)/ge; # To satisify xgettext: " > }; You could also use HTML::Template::Expr and setup a function called gettext: <tmpl_var expr=3D"gettext('Hello World')"> It's more verbose but it will work better with the cache system. If you want your syntax you could combine the two: my $gettextFilterSub =3D sub { my ($text_ref) =3D @_; $$text_ref =3D~ s/<(gettext\([^)]\))>/<tmpl_var expr=3D$1>/g; }; -sam |