Internacionalização e Localização: porque software livre é pra ser universal

Antonio S. de A. Terceiro
<terceiro@colibre.com.br>

Motivação

Uma das características mais empolgantes do software livre é sua universalidade.

No caso de vários softwares proprietários amplamente usados, para poder usar o software na seu idioma nativo o usuário precisa baixar/comprar uma cópia do software específica para o seu idioma. Além disso, a empresa fornecedora do software proprietário tem que se convencer da necessidade de ter aquele software traduzido para mais um idioma.

No software livre é diferente: para ter o software em seu idioma nativo, um usuário tem muito mais facilidade. Pode ele próprio traduzir o software, pode contratar alguém para fazer isso. Isso tudo sem nem ter que informar ao desenvolvedor original.

Por exemplo, em 25 de Julho de 2006 tínhamos os seguintes números sobre a disponibilidade de alguns softwares livres e não-livres em diferentes idiomas:

Software Número de idiomas suportados Fonte da informação
Gnome 42 Idiomas indicados como suportados em http://www.gnome.org/i18n/. Contanto traduções parciais, são 103
KDE 65 aptitude search kde-i18n- | wc -l no Debian Testing
Firefox 1.5.0.4 36 Downloads disponíveis em http://www.mozilla.com/firefox/all.html
Windows 2000 17 http://support.microsoft.com/kb/292246/EN-US/
Windows XP/2003 92 http://support.microsoft.com/kb/292246/EN-US/
Adobe Photoshop CS2 21 http://www.adobe.com/uk/products/photoshop/languages.html
The Gimp 2.2.12 40 ftp://ftp.gimp.org/pub/gimp/v2.2/gimp-2.2.0.tar.bz2
TWiki 4.0.4 10 release notes da versão 4.0.4

Na lista de idiomas suportados do Windows XP/2003 as variantes de espanhol são contadas várias vezes, ao contrário dos softwares livres. Na área de editoração de imagens digitais, o Gimp já supera o Adobe Photoshop em número de idiomas suportados.

Algo que está acima dos números é a autonomia das pessoas de se apoderarem do software livre adaptando-o para sua cultura local. O Gnome, por exemplo, tem uma tradução parcial para Iorubá. A tradução ainda é muito incipiente, mas importante de se notar é que as pessoas que falam Iorubá tem a possibilidade de traduzir por elas próprias. Eu duvido que algum dia exista uma tradução do Windows® para Iorubá, a não ser que a Microsoft seja forçada a fazer isso.

No restante desse artigo, são apresentados sob um ponto de vista técnico, diversos aspectos relacionados a internacionalização e localização.

Definições

Internacionalização é o processo de fazer com que um software tenha suporte a usuários de diversas culturas. Isso inclui a tradução da interface de usuário, mas não se limita a isso. Internacionalização é normalmente abreviada como I18N ("I", seguido de 18 letras, seguido de "N", do inglês internationalization).

Localização é o processo de adaptar um software que tenha internacionalização para uma nova cultura. Por exemplo, traduzir a interface de usuário de uma aplicação para o português do Brasil faz parte do processo de localização do software para usuários brasileiros. Localização é normalmente abreviada como L10N ("L", seguido de 10 letras, seguido de "N", do inglês localization).

Locales: informações sobre a região do usuário

locales são informações que descrevem o ambiente para um determinada cultura. Os locales representam só informações sobre o idioma. Apesar de menos usadas, também estão disponíveis informações como separador de milhares ("ponto" em português, "vírgula" em inglês), separador de parte decimal ("vírgula" em português, "ponto" em "inglês"), caracteres maísculos e minúsculos, ordenação entre caracteres entre outros. Cada um desses tipos de informação é uma categoria de locale.

Normalmente, define-se um único idioma para todas as categorias. Costumamos nos referir a essa configuração, genericamente, como locale.

Normalmente o nome de um locale é o código de um idioma + o código do país. Por exemplo, o locale para português brasileiro chama-se pt_BR. O português europeu, por sua vez, chama-se pt_PT. Além do idioma, o nome do locale pode conter também a codificação de caracteres utilizada. Por exemplo, o locale português brasileiro usando codificação UTF-8 chama-se pt_BR.utf8, já usando a codificação ISO-8859-1, pt_BR.iso88591. O nome do locale pode conter ainda um modificador opcional como sufixo, no formato @mod.

O comando locale lista as informações sobre o ambiente locale atual. Usado sem nenhuma opção, são mostrados os valores das variáveis que definem cada categoria de locale.

$ locale
LANG=pt_BR.utf8
LC_CTYPE="pt_BR.utf8"
LC_NUMERIC="pt_BR.utf8"
LC_TIME="pt_BR.utf8"
LC_COLLATE="pt_BR.utf8"
LC_MONETARY="pt_BR.utf8"
LC_MESSAGES="pt_BR.utf8"
LC_PAPER="pt_BR.utf8"
LC_NAME="pt_BR.utf8"
LC_ADDRESS="pt_BR.utf8"
LC_TELEPHONE="pt_BR.utf8"
LC_MEASUREMENT="pt_BR.utf8"
LC_IDENTIFICATION="pt_BR.utf8"
LC_ALL=

Cada uma dessa variáveis LC_* corresponde a uma categoria de locale. LC_COLLATE, por exemplo, define qual idioma considerar para ordenação de caracteres. Cada uma das categorias pode ser definida atribuindo-se um valor à variável LC_* correspondente. Por exemplo:

$ LC_COLLATE=C locale
LANG=pt_BR.utf8
LC_CTYPE="pt_BR.utf8"
LC_NUMERIC="pt_BR.utf8"
LC_TIME="pt_BR.utf8"
LC_COLLATE=C
LC_MONETARY="pt_BR.utf8"
LC_MESSAGES="pt_BR.utf8"
LC_PAPER="pt_BR.utf8"
LC_NAME="pt_BR.utf8"
LC_ADDRESS="pt_BR.utf8"
LC_TELEPHONE="pt_BR.utf8"
LC_MEASUREMENT="pt_BR.utf8"
LC_IDENTIFICATION="pt_BR.utf8"
LC_ALL=

Isso faz com que os programas que utilizam informação de locale não considerem a ordenação de caracteres do português, usando essas informações do locale default C.

A opção -a lista os locales disponíveis.

$ locale -a
C
pt_BR
pt_BR.iso88591
pt_BR.utf8

Neste caso, o sistema possui os locales C (locale padrão), pt_BR, pt_BR.iso88591 e pt_BR.utf8. Quando a codificação é omitida no nome do locale, a escolha da codificação a ser usada é dependente do sistema.

Vamos alguns aspectos influenciados pela configuração de locales. Por enquanto, configure o seu terminal para codificação ISO-8859-1. Na seção seguinte você vai entender porquê.

Vamos escrever um pequeno programa em Perl que lê linhas da entrada padrão e destaca todos os caracteres minúsculos:

#!/usr/bin/perl

use locale;
my $line;

while (defined($line = <STDIN>)) {
        $line =~ s/[[:lower:]]/($&)/g;
        print $line;
}

Suponha que esse programa chame-se lower.pl. Veja o que acontece quando ele é executado em diferentes contextos de locale:

$ LANG=C perl lower.pl
asdasdáéíóúasdsadsa
(a)(s)(d)(a)(s)(d)áéíóú(a)(s)(d)(s)(a)(d)(s)(a)
$ LANG=pt_BR.iso88591 perl lower.pl
asdasdáéíóúasdsadsa
(a)(s)(d)(a)(s)(d)(á)(é)(í)(ó)(ú)(a)(s)(d)(s)(a)(d)(s)(a)

Note que só num locale onde os caracteres com acento fazem parte do "alfabeto" eles são reconhecidos como caracteres minúsculos.

Agora vamos escrever um segundo programa, chamado chars.pl. Ele vai imprimir todos os caracteres considerados como alfanuméricos.

#!/usr/bin/perl

use locale;

print +(sort grep /\w/, map { chr } 0..255), "\n";

Note como o conceito de caracter alfanumérico varia a depender do locale:

$ LANG=C perl chars.pl
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz
$ LANG=pt_BR.iso88591 perl chars.pl
µ_0123456789aAªáÁàÀâÂåÅäÄãÃæÆbBcCçÇdDðÐeEéÉèÈêÊëËfFgGhHiIíÍìÌîÎïÏjJkKlLmMnNñÑoOºóÓòÒôÔöÖõÕøØpPqQrRsSßtTuUúÚùÙûÛüÜvVwWxXyYýÝÿzZþÞ

Gerando locales

No Debian:

# dpkg-reconfigure locales

De forma genérica:

# edit /etc/locales.gen
# locale-gen

Lidando com diferentes codificação de caracteres

Ao transferir dados textuais entre computadores é preciso que haja um consenso sobre como representar os elementos mais básicos do texto em termos de bytes, que são afinal os menores elementos de informação armazenáveis nos computadores atuais.

Segundo a Wikipedia, Codificação de caracteres ou conjunto de caracteres é um mapeamento entre uma sequência de caracteres e um outro conjunto, normalmente um dos números naturais.

Existem várias codificações atualmente em uso. A mais antiga delas é o código ASCII. O código ASCII representa as letras do alfabeto (a a z) maiúsculas e minúsculas, os numerais (0 a 9), diversos outros caracteres especiais e caracteres de controle, mapeando-os nos números naturais entre 0 e 126. No código ASCII é representál através de um único byte. De fato, um caracter ASCII só precisa de 7 bits para ser representado, sobrando 1 bit num byte.

Uma clara limitação do código ASCII é que ele não representa caracteres acentuados, impossibilitando a representação de textos em português, espanhol, francês, etc. Dessa forma, uma codificação semelhante é a ISO-8819-1. É um superconjunto do código ASCII que inclui o alfabeto latino, e representa 255 caracteres usando os 8 bits de um byte.

Unicode é um padrão que visa representar todos os caracteres utilizados nos sistemas de escrita do mundo. O Unicode associa a cada caracter um código (chamado codepoint). Por convenção, os primeiros 256 codepoints do Unicode correspondem aos 256 caracters do ISO 8859-1.

Os caracteres Unicode podem ser codificados usando um dos diferentes formatos de transformação do Unicode (Unicode Transformation Formats, UTF). UTF-8 é uma das codificações possíveis para o Unicode, que utiliza de 1 a 4 bytes para codificar cada caracter. UTF-16 é uma codificação análoga que usa 2 ou 4 bytes para codificar cada caracter. Outra codificação é UTF-32, onde são usados 4 bytes para codificar cada caracter. UTF-8 é a codificação mais popular entre estas.

A maioria dos emuladores de terminal suportam diferentes codificações. A codificação selecionada será usada para transferir para as aplicações os caracteres que são digitados pelo usuário. No GNOME Terminal, por exemplo, você pode trocar a codificação utilizada através do menu "Terminal":

gnome-terminal-encoding.png

Quando o seu terminal está configurado para uma codificação e alguma aplicação cospe dados em outra codificação, coisas estranhas acontecem. Você já deve ter visto coisas assim. smile

Para os próximos exemplos, usaremos dois arquivos com o mesmo conteúdo, a linha:
vogais: áéíóú
. A única diferença entre eles é a codificação.

Se estamos com o terminal configurado para UTF-8 ...

$ cat utf8-data
vogais: áéíóú
$ cat latin1-data
vogais: □□□

Agora com o terminal em ISO-8859-1 (latin1) ...

$ cat utf8-data
vogais: áéíóú
$ cat latin1-data
vogais: áéíóú

Como a maioria dos programas usa a informação do locale para saber em que codificação a informação deve ser apresentada, o normal é que o terminal sempre esteja configurado para a

O mesmo tipo de problema acontece com páginas web. Atire a primeira pedra quem nunca abriu uma página na qual os acentos estavam "desconfigurados"? Isso acontece porquê quem fez a página não especificou corretamente qual codificação usada para o texto daquela página.

Toda página web deve ter sua codificação informada de duas formas: a forma padrão é através dos cabeçalhos HTTP (ex. Content-Type: text/html;charset=utf-8). A geração desse cabeçalho é simples para página dinâmicas (geradas por um script), mas para páginas estáticas isso fica mais complicado. A solução é usar a tag meta para especificar o tipo do arquivo e de carona a codificação. Por exemplo, para páginas codificadas em UTF-8, pode-se usar:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Existem diversas ferramentas para conversão de codificação. O iconv é uma delas. Com o iconv selecionamos a codificação de origem de a de destino, usando as opções -f e -t respectivamente.

Por exemplo, com o terminal configurado para UTF-8:

$ iconv -f iso-8859-1 -t utf-8 latin1-data
vogais: áéíóú

E com o terminal configurado para ISO-8859-1:
$ iconv -f utf-8 -t iso-8859-1 utf8-data
vogais: áéíóú

Também existem diversas biblioteca e módulos, em várias linguagens de programação, para conversão de codificação. Em Perl, o módulo Encode realiza essa tarefa. Como exemplo, vamos escrever um pequeno programa chamado iconv.pl.

Nosso iconv.pl é bastante limitado: ele só aceita com codificação de entrada ou saída iso-8859-1 e utf-8. Tanto o iconv do sistema quanto o módulo Perl Encode suportam vários outras codificações.

#!/usr/bin/perl

use Encode;
use Getopt::Long;

my $from = 'iso-8859-1';
my $to = 'utf-8';

GetOptions (
"from=s", \$from,
"to=s", \$to,
);

foreach my $choice ($from, $to) {
        if ($choice ne 'iso-8859-1' && $choice ne 'utf-8') {
                print "$choice encoding is not supported. Exiting.\n";
                exit 1;
        }
}

my $line, $text;
while (defined($line = <STDIN>)) {
        $text = Encode::decode($from, $line);
        print Encode::encode($to, $text);
}

Vamos testar nosso iconv.pl. Com o terminal configurado para UTF-8:

$ cat latin1-data | perl iconv.pl
vogais: áéíóú

E com o terminal configurado para ISO-8859-1:

$ cat utf8-data | perl iconv.pl -f utf-8 -t iso-8859-1
vogais: áéíóú

Internacionalização de interface: inglês é só mais um idioma

Vamos ver agora como escrever um programa que suporte traduação da sua interface de usuário (janelas, menus, mensagens, etc).

TODO ...

#!/usr/bin/perl

use strict;

package Hello::I18N;
use base 'Locale::Maketext';
use Locale::Maketext::Lexicon {
        'en' => ['Auto'],
        '*' => [Gettext => '*.po'],
        _auto   => 1,
};

my $lh = Hello::I18N->get_handle() or die('What language?');

print($lh->maketext("Hello, world!\n"));

Na próxima sessão é descrito o processo de tradução propriamente dito, quando o template de mensagens é traduzido para cada idioma.

Localização de aplicações: traduzindo arquivos gettext

TODO ...

Estudo de caso: internacionalização da interface de usuário do TWiki

TODO ...

Para saber mais

Textos introdutórios, HOWTO's, etc:

Manuais de referência sobre locales:

  • $man locale
  • $man locale.gen
  • $man locale-gen

Manuais de referência sobre codificação:

  • $man iconv (ferramenta iconv)
  • $man Encode (módulo Encode do Perl)

Slides

Start presentation

Slide 1: Internacionalização e Localização: porque software livre é pra ser universal

Antonio S. de A. Terceiro
<terceiro@colibre.com.br>

Slide 2: Roadmap

  • Motivação
  • I18N e L10N
  • Locales
  • Codificações de caracteres
  • Internacionalização de interface → fazendo software traduzível
  • Localização: traduzindo aplicações
  • Estudo de caso: internacionalização de interface de usuário do TWiki

Slide 3: Motivação

twiki-sueco.png

Slide 4: Introdução

  • I18N: Internationalization → generalização
  • L10N: Localization →especialização

Slide 5: Locales

  • Informações culturais
  • listando locales disponíveis: $ locale -a
  • gerando locales: $ locale-gen

Slide 6: Codificação de caracteres

1 1 0 0 0 0 0 1

á

1 1 0 0 0 0 1 1 1 0 1 0 0 0 0 1

  • Lidando com codificações diferentes
  • conversão

Slide 7: Unicode

Unicode_logo.jpg

http://www.unicode.org/

* UTF-8, UTF-16, ...

Programando com I18N!

Na prática ...

Extração de strings

Na prática ...

Tradução

Na prática ...

Acabou

Perguntas?

-- AntonioTerceiro - 25 Jul 2006
Topic attachments
I Attachment Action Size Date Who Comment
Unicode_logo.jpgjpg Unicode_logo.jpg manage 4.2 K 25 Aug 2006 - 21:51 AntonioTerceiro  
twiki-sueco.pngpng twiki-sueco.png manage 114.2 K 26 Aug 2006 - 13:18 AntonioTerceiro  
Topic revision: r8 - 26 Aug 2006, AntonioTerceiro
 

This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki-Colivre? Send feedback