Wednesday May 28, 2008

Internationalisation perl gotcha

One of the issues to look out for when applying gettext to perl programs is variable substitution. For example:

  print "My name is $name\\n"

Should not be internationalised as:

  print gettext("My name is $name\\n");

Because the variable substitution for $name occurs before the call to gettext - hence gettext would get the text including the value of the variable $name, and would require a separate translation for every value of $name.

There are number of alternatives to this, printf or string concatenation. These work for many situations, but can present a problem when there are multiple variables being substituted and the order of the variables is different in different locales.

Tuesday May 27, 2008

Internationalising perl with gettext

The previous blog entry showed how to do internationalisation using an example in C. Unsurprisingly very similar code can be used in perl.

#!/bin/perl -w

use POSIX;
use Sun::Solaris::Utils qw(textdomain gettext bindtextdomain);

setlocale(LC_MESSAGES,"fr");
bindtextdomain("EX","/export/home/perl_test/locale");
textdomain("EX");

printf gettext("test\\n");

The perl code uses the same text domain, and same binding to end up using the same message catalogue as the C example. So again this code will output "notest" rather than "test" when run.

One thing that's caught me a couple of times is the use of the setting LC_MESSAGES in the call to setlocale. It's tempting to use LC_ALL which means that all text should be translated, but that does not work - I believe the reason is that a sublocale needs to be specified. The higher level locale may have sublocales with conflicting settings - for example an application that outputs messages in English could have Pounds or Dollars as currency.

The other thing to be aware of is that the call to bindtextdomain needs to be performed before that domain is used by the textdomain call.

Friday May 23, 2008

Internationalising perl using gettext

Just looking at using gettext to internationalise a perl program. Some functions that are coded in perl are kstat and psrinfo.

Wednesday Jan 09, 2008

Internationalising a perl program

I have a number of useful perl scripts, they all have English messages, and to be friendly need to be internationalised (or internationalized, depending on your locale). Fortunately, there's a perl module called Maketext which appears to do exactly what I need. In fact it seems to be deceptively simple, compared to the horror described in this article. Here's an example program:

$ more test.pl
#!/bin/perl -w

printf ("%i of %i optimised\\n",1,7);

To make the internationalisation happen the print statements need to be converted into calls to maketext. Maketext has a slightly different syntax since the order that the parameters are written depends on the language that they are written in. The converted version of the code looks like:

$ more test.pl
#!/bin/perl -w

use Test::L10N;

my $lang = Test::L10N->get_handle() || die "Language support error";

print $lang->maketext("[_1] of [_2] optimised\\n",1,7);

Rather than use the above version of the code, the behaviour of which will depend on the locale that it's run in, I'll modify it to assume that it's run in a US English locale.

$ more test.pl
#!/bin/perl -w

use Test::L10N;

my $lang = Test::L10N->get_handle('en_us') || die "Language support error";

print $lang->maketext("[_1] of [_2] optimised\\n",1,7);

The code now makes use of a perl module, called L10N.pm that is specific for my "Test" program. This module needs to be created in a Test subdirectory, and the module basically exists to include the Maketext module from the Locale package:

$ more Test/L10N.pm
package Test::L10N;
use base qw(Locale::Maketext);
1;

For English locales, we'll default to keeping the original phrase as the output phrase.

$ more Test/L10N/en.pm
package Test::L10N::en;

use base qw(Test::L10N);
%Lexicon=('_AUTO'=>1,);

1;

If we want to translate the message into US English, then we add a en_us.pm file:

$ more Test/L10N/en_us.pm
package Test::L10N::en_us;

use base qw(Test::L10N);
%Lexicon=("[_1] of [_2] optimised\\n"=>"[_1] of [_2] optimized\\n",);

1;

The output of the program is 1 of 7 optimized rather than 1 of 7 optimised. Much clearer.

About

Darryl Gove is a senior engineer in the Solaris Studio team, working on optimising applications and benchmarks for current and future processors. He is also the author of the books:
Multicore Application Programming
Solaris Application Programming
The Developer's Edge

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
5
6
8
9
10
12
13
14
15
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
Bookmarks
The Developer's Edge
Solaris Application Programming
Publications
Webcasts
Presentations
OpenSPARC Book
Multicore Application Programming
Docs