quarta-feira, 2 de maio de 2007

Insanifying, Parte II

Terceiro e último dia da competição e do FISL. No dia anterior, os problemas exigiam que se conhecesse o mínimo da estrutura do projeto Debian. Quem não soubesse como fazer algo, poderia pedir ao Felipe ou ao Otávio e eles informariam. Poderia ainda pedir a qualquer um dos presentes no FISL ou mesmo a quem estivesse on-line. Porém, isso acabaria consumindo parte do tempo das equipes.

Eu uso o Debian nos meus servidores desde o lançamento do Potato 2.2r5 no início de 2002. Naquela época um dos meus hobbies era testar diferentes sistemas operacionais. No meu computador eu tinha cinco sistemas instalados ao mesmo tempo (Conectiva & Mandrake (agora Mandriva), NetBSD, OpenBSD, Windows e mais uma partição vazia para ficar testando outros...) quando resolvi instalar o Debian e, gradualmente, ir desinstalando os que estavam instalados... :-)

Com o lançamento do Ubuntu Warty Warthog em 2004, eu acabei deixando o Debian para ficar com o Ubuntu, que como todos devem saber, é baseada no próprio Debian. Pois bem, posso dizer que durante estes cinco anos fiquei bem familiarizado com o Debian/Ubuntu. Isso acabou ajudando a nossa equipe, pois praticamente todas as dúvidas do Guilherme e do Kalecser estavam na ponta da minha língua e acabei por me tornar uma espécie de líder para a equipe... :-)

Voltando ao terceiro dia. Novamente fizemos um círculo para receber as instruções. Dessa vez o desafio consistia em torno de um único problema, mais uma vez envolvendo o tema da fase anterior. O Debian é composto por mais de 18 mil pacotes, dos quais uma grande maioria possui suporte a internacionalização (i18n, para ser mais conciso).

A questão é que uma quantidade razoável das mensagens que precisam ser traduzidas se repetem, ou no mínimo são bastante semelhantes. Isso gera a necessidade da utilização de alguma ferramenta que implemente o conceito de Translation Memory, de forma a agilizar o processo de tradução, bem como manter a consistência quando forem utilizados termos semelhantes.

Só para dar um exemplo: o termo 'Save' está presente no menu de praticamente qualquer aplicativo gráfico. A idéia é que a tradução de todas as mensagens de todos os pacotes que utilizem esse termo fiquem iguais, no caso 'Salvar'. Isso evita a ocorrência de discrepâncias nas traduções, muito comuns em casos onde diferentes pessoas colaboram no processo de tradução. Também é importante que quando o termo for usado em outras mensagens (Save as/Save all/...) a tradução seja sugerida, agilizando o processo e reduzindo possíveis erros de consistência.

Nós recebemos um arquivo de 70MB, com uma amostra das traduções utilizadas por alguns pacotes, totalizando cerca de 300MB depois de descompactado. Cabe lembrar que essa amostra representa apenas um percentual do volume de mensagens presentes nos pacotes do Debian. Segundo o Felipe e o Otávio, atualmente nenhum dos softwares existentes (livres ou não) consegue carregar toda a base de traduções dos idiomas presentes no Debian:

>>> import re, urllib
>>> url = 'http://www.debian.org/international/l10n/po'
>>> page = urllib.urlopen(url).read()
>>> uls = re.findall('<ul>.*<ul>(.*)</ul>', page, re.DOTALL)[0]
>>> len(re.findall('<li>(.*)</li>', uls))
226

(Para os mais desavisados, o programinha acima acessa o site do Debian e salva uma cópia da página com a relação dos idiomas existentes, filtrando para ficar apenas com o segundo bloco de itens, já que o primeiro contém o menu de navegação e imprime o número de itens encontrados.)

Sim... existem 226 idiomas (ou variações de idiomas) no Debian! Impressionante!

A tarefa consistia em escrever uma especificação e realizar a implementação de um software para auxiliar no processo de tradução, permitindo que:

  • administradores possam adicionar novos pacotes no sistema;
  • tradutores possam efetuar as traduções fazendo uso do recurso de Memory Translation;
  • revisores possam acessar o sistema e sugerir alterações nas traduções já existentes.

A propósito, o nosso programa acabou sendo chamado de ATR, em função de ter que atender às necessidades das 3 classes: Administradores, Tradutores e Revisores... :-)

A primeira coisa que fizemos foi definir a estratégia. Mais uma vez sabíamos que não seria possível concluir totalmente a tarefa em tempo. Então decidimos que seria melhor fazer pelo menos um pouco de cada uma das coisas, ao invés de fazer uma das coisas bem-feita e ignorar as outras.

Precisaríamos de algo que fizesse a indexação de texto de forma rápida e sem consumir recursos demasiados do sistema. Depois de um rápido brainstorming, optamos pelo uso do Lucene, devido ao conjunto das suas características, que já contempla diferentes funções para a busca de texto. Também decidimos que a aplicação teria interface gráfica, ao invés de rodar em modo texto no console.

Como o Guilherme e o Kalecser tinham experiência na mesma linguagem de programação (Java), optamos pela seguinte divisão de tarefas:

Dorneles
especificação do sistema e desenvolvimento de qualquer coisa que levasse muito tempo em Java
Guilherme
parser dos arquivos de tradução e integração com o Lucene
Kalecser
implementação da interface gráfica

Mais uma vez o trabalho colaborativo seria fundamental. Continuamos usando o Google Docs para a especificação, mas iríamos precisar de um sistema de controle de versão para o código. Então instalei e configurei um servidor de Subversion na minha máquina. Aprendi que no mundo Java praticamente ninguém vive sem o Eclipse... e aprendi como instalar o plugin de Subversion nele também... :-)

Para termos uma noção de como era a interface gráfica do softwares já existentes, usamos o valioso serviço do Google Images. Com isso, o Kalecser e eu rascunhamos o que nós consideramos ser a melhor solução para o nosso programa.

Em seguida o Kalercer precisou extrair a relação dos idiomas disponíveis para popular um combo na tela e isso iria levar um certo tempinho em Java. Então ele pediu e eu escrevi rapidamente um programinha (4 linhas, se não me falha a memória) em Python e devolvi a saída no formato que ele havia solicitado.

Enquanto isso o Guilherme quebrava a cabeça para ver se o Java tinha algum recurso nativo para ser usado na manipulação de arquivos de catálogo de mensagens do gettext (PO e POT). Se não me engano, acabamos desenvolvendo um parser temporário e implementando nosso próprio algoritmo de busca de texto por similaridade.

Por fim, acabamos fazendo mais algumas pseudo-implementações de características que achávamos importante constar no sistema e nos preparamos para empacotar e documentar o que havíamos desenvolvido até então. O empacotamento acabou virando POG (esquecemos até a licença!), pois já tínhamos esgotado o tempo e não pudemos gerar um pacotinho Debian nos conformes... Nossa solução ficou longe do que constava na especificação, mas acredito que fizemos um bom trabalho durante o tempo determinado.

É claro que seria melhor se recebêssemos uma especificação já pronta e tivéssemos apenas que programar. O problema é que o pessoal do Debian ainda não tem uma solução para isso. Dessa forma, usaram a oportunidade de ter 12 cérebros a disposição para colher algumas idéias que poderão vir a se tornar a futura ferramenta.

Obviamente que tratava-se de um evento de programação, então entendo o fato de termos que ter programado algo para mostrar no final do dia. Caso os doze participantes tivessem trabalhado juntos, certamente o Debian teria se beneficiado mais, porém isso não seria possível nesse tipo de evento.

Encerramos a competição sem ter a menor idéia de como havia sido o nosso desempenho em comparação com as outras três equipes. Esse suspense durou mais algumas horas até o anúncio do resultado final. Mas isso é assunto para o próximo post, que só vai sair depois que o Felipe e o Otávio me enviarem o material que eles haviam prometido... ;-)

0 comentários: