[LA.pm] fwd: Internationalizing a Perl application
David Fetter
david at fetter.org
Wed Jan 17 12:38:08 PST 2007
Folks,
I'd like to get this one in the archives. Thanks to Nik Clayton of
London.pm for this, and to David Alban for asking London.pm about it :)
Cheers,
D
On Tue, Jan 16, 2007 at 03:02:31PM +0000, Nik Clayton wrote:
> >With DBI-Link's growing popularity world-wide, I'm getting more
> >requests for translation of the docs and strings. This presents a
> >huge bunch of opportunities for me to make mistakes, so I'm asking for
> >the collective wisdom out there.
> >
> >* Where do I start?
>
> Ignoring the documentation aspect, and just dealing with your application's
> output for the time being.
>
> You need to:
>
> a) Have a mechanism that, given a string-code, can return the correct
> version of that string given the users preferred language choice.
>
> b) Have a mechanism to allow users to specify their preferred language.
>
> c) Have translations of your strings available.
>
> For (a) and (b) I recommend using Locale::Maketext::Simple, which does most
> of the hard work for you. This supports keeping your translations in
> separate files (en.po for English, fr.po for French, and so on), and, given
> a string, finds the translation of that string.
>
> It handles most of the hard work concerning what to do with different
> languages and how they behave with things like plurals.
>
> I do this in SVN::Web. Internally, any string that might be displayed to
> the user is represented as "(short string)" -- I use brackets because it
> makes it obvious in the user interface if an untranslated string is being
> displayed.
>
> Then the proper representations of those strings (even the English ones)
> are kept in separate files. Locale::Maketext::Simple provides loc_lang()
> (to set the current language) and loc() (to look up a strings
> representation in the language dictionary). So the code looks something
> like:
>
> my $lang = get_users_preferred_language(); # 'en', 'fr', etc
>
> loc_lang($lang); # Set the preferred language
>
> print loc('(choose repos)');
>
> If $lang is 'en' then it will look in the English dictionary, which has
> this entry;
>
> msgid "(choose repos)"
> msgstr "Please select a repository to browse:"
>
> fr.po has this in it.
>
> msgid "(choose repos)"
> msgstr "Veuillez selectionner le depot parcourir :"
>
> Same message id, different message string.
>
> You can either use Locale::Maketext::Simple as is, or you can subclass it
> if you need new functionality. I had to do that in SVN::Web, where I need
> to be able to add new paths to language dictionaries at runtime. You can
> see the resulting code in SVN::Web::I18N.
>
> So, broadly:
>
> 1. Get Locale::Maketext::Simple working
>
> 2. Use loc_lang() to set the current language
>
> 3. Replace code like
>
> print "This is a string";
>
> with code like
>
> print loc("(this-is-a-string)");
>
> and in en.po have
>
> msgid "(this-is-a-string)"
> msgstr "This is a string"
>
> You don't have to use the same convention with braces that I have.
>
> You can do variable interpolation in to translated strings using %1, %2, %3
> placeholders. For example, given this entry in the .po file:
>
> msgid "(file not found: %1 %2)"
> msgstr "File '%1' could not be found in directory '%2'"
>
> you'd write code like so:
>
> print loc('(file not found: %1 %2)', $file, $directory);
>
> Suppose you then want to change the output. The code stays the same, but
> the msgstr becomes:
>
> msgstr "Directory %2 does not contain file %1"
>
> Your dictionary can also specify many alternatives depending on the value
> of a parameter. For example, suppose you want to write:
>
> my $duration = a_long_process();
> print "Process took $duration seconds";
>
> But you might be on really fast hardware, and it only took one second.
> Typically you might solve that with:
>
> print "Process took $duration second" . $duration != 1 ? 's' : '';
>
> With message dictionaries you can put that logic in the dictionary instead.
>
> print loc('(%1 second)'); # in the code
>
> msgid "(%1 second)"
> msgstr "%quant(%1, second, seconds)"
>
> See SVN::Web::I18N for code, Locale::Maketext::TPJ13 for an article from
> "The Perl Journal" which should help make some of this clear.
>
> Hope that helps,
>
> N
--
David Fetter <david at fetter.org> http://fetter.org/
phone: +1 415 235 3778 AIM: dfetter666
Skype: davidfetter
Remember to vote!
More information about the Losangeles-pm
mailing list