Perl Brasil

Pesquisar

Documentação

Planeta

Eventos

Comunidade

r5 - 07 Nov 2007 - JoenioCosta

Fazendo um HelloWorld falar vários idiomas

Problema

Como fazer um sistema com suporte a L10N? Você precisa que seu sistema tenha suporte a vários idiomas e que novos idiomas sejam adicionados a qualquer momento?

Solução

Utilize o módulo Locale::Maketext em conjunto com Locale::Maketext::Lexicon.

Discussão

Abaixo segue um simples helloworld modo texto a ser executado via linha de comando... O exemplo foi desenvolvido e testado em ambiente Gnu/Linux utilizando Perl v5.8.8, mas você deve consiguir executá-lo em qualquer computador que tenha Perl instalado.

HelloWorld::L10N

Primeiro devemos criar um módulo que use como base o Locale::Maketext.

   package HelloWorld::L10N;
   use base 'Locale::Maketext';
   use Locale::Maketext::Lexicon {
      'en' => ['Auto'],
      '*'  => ['Gettext' => 'po/*/hello.po'],
      _auto => 1,
   };
   my $lh = __PACKAGE__->get_handle();
   sub _ { $lh->maketext(@_) }
   1;

Neste módulo definimos que:

Como estamos numa aplicação via linha de comando o idioma utilizado será definido através da variável de ambiente LANGUAGE, o Locale::Maketext irá detectar automagicamente o idioma a ser utilizado através da chamada __PACKAGE__->get_handle().

A função _ definida na ultima linha deste módulo irá criar as mensagens "localizadas", ou seja, mensagens traduzidas para o idioma corrente detectado no ambiente onde o sistema será executado. Esta função poderia ter qualquer outro nome, mas utilizar um simples caracter _ evita poluição no código, pois teoricamente esta função deverá ser chamada em quase todos os locais do sistema.

HelloWorld

Agora vamos criar o módulo HelloWorld que possui a funcionalidade do nosso sistema em sí.

   package HelloWorld;
   use HelloWorld::l10n;
   use Exporter 'import';
   @EXPORT = qw( hello found );

   sub hello {
      return _('Hello world!'), "\n";
   }
   sub found {
      return _("Found [*,_1,file,files].", $_[0]), "\n";
   }

   1;

Este módulo faz utilização do módulo acima e define os métodos hello e found, onde apenas retornam as mensagens 'Hello world!' e "Found [*,_1,file,files]."localizados respectivamente. O método found foi utilizado apenas para exemplificar a possibilidade de tratamento diferenciado para mensagens no singular e plural pelo Locale::Maketext.

helloworld.pl executando...

Abaixo o script que utiliza o módulo HelloWorld:

   #!/usr/bin/perl
   use strict;
   use HelloWorld;
   print hello();
   print found(1);
   print found(3);

Defina seu ambiente como Portugues do Brasil alterando a variável de ambiente LANGUAGE para pt_BR e execute o script:

   $ perl helloworld.pl
   $ Hello world!
   $ Found 1 file.
   $ Found 3 files.

Não aconteceu nada, correto? Claro! Porque nós ainda nao geramos os arquivos com as traduções...

makepot.pl traduzindo...

O Locale::Maketext::Lexicon traz em seu conjundo de módulos o módulo Locale::Maketext::Extract que é uma mão na roda para executar a tarefa de varrer todos os fontes do seu sistema em busca de mensagens que devem ser traduzidas.

   #!/usr/bin/perl
   use strict;
   use warnings;
   use Locale::Maketext::Extract;
   my $Ext = Locale::Maketext::Extract->new();
   mkdir './po' unless -e './po';
   $Ext->read_po('po/hello.pot') if -e 'po/hello.pot';
   $Ext->extract_file($_) for (<*.pl>, <*.pm>);
   $Ext->compile(1);
   $Ext->write_po('po/hello.pot');

O script acima faz uso desse módulo para percorrer todos os arquivos com extensão .pl e .pm em busca de mensagens a ser traduzidas e as salva em po/hello.pot. Este arquivo .pot é um template a ser utilizado para iniciar a tradução dos diversos idiomas que voce pretente suportar em seu sistema e não deve ser editado manualmente.

hello.pot

   # SOME DESCRIPTIVE TITLE.
   # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
   # This file is distributed under the same license as the PACKAGE package.
   # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
   #
   #, fuzzy
   msgid ""
   msgstr ""
   "Project-Id-Version: PACKAGE VERSION\n"
   "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
   "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
   "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
   "Language-Team: LANGUAGE <LL@li.org>\n"
   "MIME-Version: 1.0\n"
   "Content-Type: text/plain; charset=CHARSET\n"
   "Content-Transfer-Encoding: 8bit\n"

   #: HelloWorld.pm:11
   #. ($_[0])
   msgid "Found [*,_1,file,files]."
   msgstr ""

   #: HelloWorld.pm:8
   msgid "Hello world!"
   msgstr ""

A execução do script deverá gerar o arquivo hello.pot semelhante ao arquivo acima no diretório po, para iniciar a tradução para o português do Brasil crie a pasta pt_BR dentro de po, copie o arquivo hello.pot para lá e altere a extensão dele para .po.

Cada entrada no arquivo acima possui um comenário (#: HelloWorld.pm:8) indicando onde a mensagem está seguido da mensagem original (msgid "Hello world!") e finalmente a mensagem traduzida (msgstr ""). Aqui a mensagem não deve ser traduzida, a tradução deve ser feita somente no arquivo correspondente ao idioma localizado na estrutura de diretórios dentro de po.

pt_BR/hello.po

Agora é só traduzir as mensagens como no exemplo abaixo...

   # SOME DESCRIPTIVE TITLE.
   # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
   # This file is distributed under the same license as the PACKAGE package.
   # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
   #
   #, fuzzy
   msgid ""
   msgstr ""
   "Project-Id-Version: PACKAGE VERSION\n"
   "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
   "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
   "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
   "Language-Team: LANGUAGE <LL@li.org>\n"
   "MIME-Version: 1.0\n"
   "Content-Type: text/plain; charset=CHARSET\n"
   "Content-Transfer-Encoding: 8bit\n"

   #: HelloWorld.pm:11
   #. ($_[0])
   msgid "Found [*,_1,file,files]."
   msgstr "Encontrado [*,_1,arquivo,arquivoss]."

   #: HelloWorld.pm:8
   msgid "Hello world!"
   msgstr "Alô mundo!"

ps.: Note que a mensagem "Found [*,_1,file,files]." traz a palavra file no singular e no plural, isto é útil para que seja possível adaptar a tradução corretamente para idiomas que possuem tratamento diferenciado para essas duas formas.

... e executar o script helloworld.pl para ver o resultado final:

   $ perl helloworld.pl
   $ Alô mundo!
   $ Encontrado 1 arquivo.
   $ Encontrado 3 arquivos.

Referências

Comentários