PO4A(7)

NOME
po4a - framework para traduzir documentação e outros materiais

Introdução
A missão do projeto po4a (em inglês, PO for anything) é facilitar as traduções (e o mais interessante, a manutenção de traduções) usando ferramentas de gettext em áreas onde elas não eram esperadas, como documentação.

Sumário
Esse documento é organizado da seguinte forma:

1 Por que eu deveria usar po4a? O que tem de bom nele?
    Este capítulo introdutório explica a motivação do projeto e sua filosofia. Você deveria ler este primeiro, se você está em processo de avaliação do po4a para suas próprias traduções.

2 Como usar po4a?
    Este capítulo é um tipo de manual de referência, tentando responder as perguntas dos usuários e dar a você um entendimento melhor do processo como um todo. Ele introduz como fazer coisas com po4a e serve como uma introdução à documentação das ferramentas específicas.

    COMO começar uma nova tradução?
    COMO alterar a tradução de volta para um arquivo de documentação?
    COMO atualizar uma tradução de po4a?
    COMO converter uma tradução pré-existente para po4a?
    COMO adicionar um texto extra às traduções (ex.: nome do tradutor)?
    COMO fazer tudo isso em uma invocação de programa?
    COMO personalizar o po4a?
3 Como ele funciona?
    Este capítulo dá a você uma visão geral da parte interna do po4a, de forma que você pode se sentir mais confiante para nos ajudar a manter e melhorá-lo. ele também pode ajudá-lo a entender o porquê de ele não funcionar da forma que você esperava, e como resolver seus problemas.

4 FAQ
    Este capítulo agrupa as perguntas frequentes (FAQ). Na verdade, a maioria das perguntas até agora puderam ser formuladas dessa forma: "Porque ele é projetado dessa forma e não dessa outra?" Se você pensa que po4a não é a resposta correta para tradução de documentação, você deveria considerar ler esta seção. Se ele não responder suas perguntas, por favor entre em contato conosco na lista de discussão <po4a-devel@lists.alioth.debian.org>. Nós adoramos feedback.

5 Notas específicas sobre módulos
    Este capítulo apresenta as especificidades de cada módulo do ponto de vista do autor original e do tradutor. Leia isso para aprender a sintaxe que você vai encontrar ao traduzir as coisas neste módulo, ou as regras que você deveria ser no seu documento original para tornar a vida dos tradutores mais fácil.

    Na verdade, essa seção não é realmente parte desse documento. Ao invés disso, ela é colocada na documentação de cada módulo. Isso ajuda a assegurar que a informação está atualizada mantendo a documentação e o código juntos.

Por que eu deveria usar po4a? O que tem de bom nele?
Eu gosto da ideia de software de código aberto, tornando possível para todos acessar o software e seu código fonte. Mas por ser francês, estou ciente de que a licença não é a única restrição à abertura do software: um software livre não traduzido é inútil para aqueles que não sabem inglês e, então, nós ainda temos mais trabalho para disponibilizar para realmente todo mundo por aí.

A percepção dessa situação aos atores do código do aberto tem melhorado drasticamente nos últimos tempos. Nós, como tradutores, vencemos a primeira batalha e convencemos a todos a importância da tradução. Mas, infelizmente, essa era uma parte fácil. Agora, nós temos que fazer o trabalho e realmente traduzir todas essas coisas.

Na verdade, softwares de código aberto se beneficiam de um nível decente de tradução, graças a maravilhosa suíte de ferramentas do gettext. Ele é capaz de extrair as strings para traduzir a partir do programa, apresentar um formato uniforme para tradutores e, então, usar o resultado do seus trabalhos em tempo de execução para exibir mensagens traduzidas para o usuário.

But the situation is rather different when it comes to documentation. Too often, the translated documentation is not visible enough (not distributed as a part of the program), only partial, or not up to date. This last situation is by far the worst possible one. Outdated translation can turn out to be worse than no translation at all to the users by describing old program behavior which are not in use anymore.

  O problema para resolver
Tradução de documentação não é muito difícil em si. Textos são bem maiores do que as mensagens do programa e, portanto, demoram mais para se alcançar, mas nenhuma habilidade técnica é realmente necessária para isso. A parte difícil aparece quando você tem que manter o seu trabalho. A detecção de quais partes mudaram e a necessidade de se manter atualizada é muito difícil, propensa a erro e muito desagradável. Eu acho que isso explica o porquê de várias documentações por aí estão desatualizadas.

  As respostas do po4a
Então, a função do po4a é tornar a tradução de documentação manutenível. A ideia é reusar a metodologia do gettext para esse novo campo. Assim como no gettext, textos são extraídos de suas localizações originais para estar presente em um formato uniforme para os tradutores. As ferramentas clássicas do gettext os ajudam a atualizar seus trabalhos quando um novo lançamento do original surge. Mas para diferenciar do modelo clássico do gettext, as traduções são, então, reinjetadas na estrutura do documento original de forma que elas podem ser processadas e distribuídas igual como a versão em inglês.

Graças a isso, a descoberta de quais partes do documento foram alteradas e que precisam ser atualizadas se torna mais fácil. Outra coisa boa é que as ferramentas vão fazer a maior parte do trabalho quando a estrutura do documento original estiver fundamentalmente reorganizado e quando alguns capítulos tiverem sido movidos, mesclados ou divididos. Ao extrair o texto para traduzir da estrutura do documento, ele também afasta você da complexidade da formatação do texto e reduz suas chances de acabar com um documento quebrado (mesmo que ele não previna completamente você de fazer isso).

Por favor, veja também o FAQ abaixo neste documento para uma lista mais completa de vantagens e desvantagens desta abordagem.

  Formatos suportados
Atualmente, essa abordagem tem sido implementada com sucesso em vários formatos de formatação de texto:

man

O bom e velho formato de páginas de manual, usado por tantos programas por aí. O suporte do po4a é muito bem-vindo, considerando que esse formato é de certa forma difícil de usar e não exatamente amigável para novatos. O módulo Locale::Po4a::Man(3pm) também possui suporte ao formato mdoc, usado pelas páginas de manual do BSD (elas também são bens comuns no Linux).

pod

Esse é o formato da documentação online de Perl, ou Perl Online Documentation. A própria linguagem e extensões são documentadas dessa forma, assim como a maioria dos scripts Perl existentes. Isso facilita a manter a documentação ferto do real código embutindo-os no mesmo arquivo. Isso torna a vida dos programadores mais fácil, mas infelizmente, não a do tradutor.

sgml

Mesmo se de certa forma tenha sido substituído nos dias de hoje pelo XML, esse formato ainda é usado com certa frequência por documentos que são maiores do algumas telas. Ele permite que você faça livros completos. Atualizar a tradução de documentos grandes pode se mostrar ser um verdadeiro pesadelo. diff se mostra frequentemente inútil quando o texto original foi recuado depois da atualização. Por sorte, po4a pode ajudar você nesse processo.

Atualmente, há suporte apenas ao DebianDoc e o DocBook DTD, mas a adição de suporte a um novo é realmente fácil. É possível até mesmo usar po4a em um SGML DTD desconhecido sem alterar o código, desde que sejam fornecidas as informações necessárias na linha de comando. Veja Locale::Po4a::Sgml(3pm) para mais detalhes.

TeX / LaTeX

O formato LaTeX é um formato de documentação mais usado no mundo de software livre e para publicações. O módulo Locale::Po4a::LaTeX(3pm) foi testado com a documentação do Python, um livro e algumas apresentações.

texinfo

Toda a documentação do GNU é escrita neste formato (esse é até mesmo um dos requisitos para se tornar um projeto GNU oficial). O suporte a Locale::Po4a::Texinfo(3pm) no po4a ainda está nas fases iniciais. Por favor relate eventuais erros e requisição por recursos.

xml

O formato XML é um formato base para muitos formatos de documentação.

Atualmente, po4a possui suporte a DocBook DTD. Veja Locale::Po4a::Docbook(3pm) para mais detalhes.

outros

Po4a também pode manipular alguns formatos mais raros ou especializados, como a documentação de opções de compilação dos kernels 2.4.x ou diagramas produzidos pela ferramenta Dia. A adição de um novo formato é normalmente muito fácil e a tarefa principal é fazer um analisador do seu formato alvo. Veja Locale::Po4a::TransTractor(3pm) para mais informações sobre isso.

  Formatos sem suporte
Infelizmente, po4a ainda não tem suporte a vários formatos de documentação.

Há uma grande quantidade de formatos que nós gostaríamos que po4a tivesse suporte, e não somente de documentação. Realmente, nós miramos em acertar todos os "furos de mercado" deixados pelas ferramentas clássicas do gettext. Isos envolve descrições de pacotes (deb e rpm), perguntas de scripts de instalação de pacotes, changelogs de pacotes e todos formatos de arquivo especializados como cenários de jogos e arquivos de recursos do wine.

Como usar po4a?
Este capítulo é um tipo de manual de referência, tentando responder as perguntas dos usuários e dar a você um entendimento melhor do processo como um todo. Ele introduz como fazer coisas com po4a e serve como uma introdução à documentação das ferramentas específicas.

  Visão geral gráfica
O esquema a seguir dá uma visão geral do processo de tradução de documentação usando po4a. Não tenha medo pela sua complexidade aparente, pois ela vem do fato de que todo o processo está representado aqui. Assim que você tiver convertido seu projeto para po4a, apenas a parte da direita é relevante.

Note que mestre.doc é tido como um exemplo de documentação a ser traduzida etradução.doc é o texto tradução correspondente. O sufixo poderia ser .pod, .xml ou .sgml, dependendo do seu formato. Cada parte da imagem será detalhada nas próximas seções.

                                   mestre.doc
                                       |
                                       V
     +<-----<----+<-----<-----<--------+------->-------->-------+
     :           |                     |                        :
 {tradução}      |       { atualização de mestre.doc }          :
     :           |                     |                        :
   XX.doc        |                     V                        V
 (opcional)      |                 mestre.doc ->-------->------>+
     :           |                  (novo)                      |
     V           V                     |                        |
  [po4a-gettextize]  doc.XX.po---->+   |                        |
          |           (velho)      |   |                        |
          |              ^         V   V                        |
          |              |     [po4a-updatepo]                  |
          V              |           |                          V
     tradução.pot        ^           V                          |
          |              |       doc.XX.po                      |
          |              |       (incerto)                      |
     { tradução }        |           |                          |
          |              ^           V                          V
          |              |    {edição manual}                   |
          |              |           |                          |
          V              |           V                          V
      doc.XX.po --->---->+<---<-- doc.XX.po    adendo      mestre.doc
      (inicial)                 (atualizado)  (opcional)  (atualizado)
          :                          |            |             |
          :                          V            |             |
          +----->----->----->------> +            |             |
                                     |            |             |
                                     V            V             V
                                     +------>-----+------<------+
                                                  |
                                                  V
                                           [po4a-translate]
                                                  |
                                                  V
                                                XX.doc
                                            (atualizado)

Na parte da esquerda, a conversão de uma tradução não usando po4a para esse sistema é mostrada. No topo da parte da direita, a ação do autor original está descrita (atualização da documentação). O meio da parte da direita é onde as ações automáticas do po4a estão descritas. Os novos materiais são extraídos e comparados com a tradução existente. Partes que não foram alteradas são encontradas e a tradução anterior é usada. Partes que foram parcialmente modificadas também são conectadas à tradução anterior, mas com uma marcação indicando que a tradução deve ser atualizada. A parte inferior da figura mostra como um documento formatado é compilado.

Na verdade, como um tradutor, a única operação manual que você tem que fazer é a parte marcada {edição manual}. Sim, me desculpe, mas o po4a ajuda você a traduzir. Ele não traduz para você...

  COMO começar uma nova tradução?
Esta seção apresenta as etapas necessárias para começar uma nova tradução com po4a. Os refinamentos envolvidos na conversão de um projeto existente para esse sistema estão detalhados na seção relevante.

Para começar uma nova tradução usando po4a, você tem que seguir as etapas a seguir:

-   Extraia o texto que você tem que ser traduzido do documento <mestre.doc> original para um arquivo do novo modelo de tradução <tradução.pot> (o formato gettext). Para isso, use o programa po4a-gettextize desta forma:

      $ po4a-gettextize -f <formato> -m <mestre.doc> -p <tradução.pot>

    <formato> normalmente é o formato usado no documento mestre.doc. Como esperado, a saída vai para tradução.pot. Por favor, veja po4a-gettextize(1) para mais detalhes sobre as opções existentes.

-   Realmente traduza o que deveria ser traduzido. Para isso, você tem que renomear o arquivo POT para, por exemplo, doc.XX.po (sendo XX o código ISO639 do idioma para o qual você está traduzindo, ex.: fr para francês) e edite o arquivo resultante. Normalmente, é uma boa ideia não nomear o arquivo XX.po para evitar confusão com a tradução das mensagens do programa, mas a decisão é sua. Não se esqueça de atualizar os cabeçalhos dos arquivos PO, pois eles são importantes.

    A tradução pode ser feita ser feita usando o modo PO do Emacs ou do, Lokalize (baseado no KDE), Gtranslator (baseado no GNOME) ou qualquer outro programa que você preferir usar para isso (ex.: Virtaal).

    Se você prefere aprender mais sobre isso, você definitivamente precisa ver a documentação do gettext, disponível no pacote gettext-doc.

  COMO alterar a tradução de volta para um arquivo de documentação?
Assim que você finalizar com a tradução, você quer pegar a documentação traduzida e distribuí-la para os usuários junto com o original. Para isso, use o programa po4a-translate(1) dessa forma (sendo XX o código do idioma):

  $ po4a-translate -f <formato> -m <mestre.doc> -p <doc.XX.po> -l <XX.doc>

Como antes, <formato> é o formato usado no documento mestre.doc. Mas dessa vez, o arquivo PO fornecido com a opção -p é parte da entrada. Essa é a sua tradução. A saída vai para XX.doc.

Por favor, veja po4a-translate(1) para mais detalhes.

  COMO atualizar uma tradução de po4a?
Para atualizar sua tradução quando o arquivo original mestre.doc foi alterado, use o programa po4a-updatepo(1) dessa forma:

  $ po4a-updatepo -f <formato> -m <novo_mestre.doc> -p <doc_antigo.XX.po>

(Por favor, veja po4a-updatepo(1) para mais detalhes)

Normalmente, o novo parágrafo no documento não será traduzido magicamente no arquivo PO com esta operação e você vai precisar atualizar o arquivo PO manualmente. Da mesma forma, você pode ter que retrabalhar a tradução por parágrafos que foram um pouco modificados. Para certificar-se de que você vai perder nenhum deles, eles são marcados como "fuzzy" (aproximado) durante o processo e você tem que remover essa marcação antes que a tradução possa ser usada por po4a-translate. como a tradução inicial, o melhor a se fazer é usar aqui o seu editor de PO favorito.

Assim que seu arquivo PO estiver atualizado novamente, sem qualquer string não traduzida ou incerta, você pode gerar um arquivo de documentação traduzida, como explicado na seção anterior.

  COMO converter uma tradução pré-existente para po4a?
Geralmente, você costumava traduzir manualmente a documentação até que uma grande reorganização do mestre.doc original aconteceu. Então após algumas tentativas desagradáveis com diff ou ferramentas similares, você quer converter para po4a. Mas, é claro, você não quer perder sua tradução existente no processo. Não se preocupe, esse caso também é manipulado pelas ferramentas do po4a e é chamado de gettextização.

A chave aqui é ter a mesma estrutura no documento traduzido e no original, de forma que as ferramentas possam conferir o conteúdo corretamente.

Se você tiver sorte (isso é, se as estruturas de ambos documentos corresponderem perfeitamente), isso vai funcionar de forma transparente e você vai estar pronto em poucos segundos. Do contrário, você pode entender o porquê desse processo ter um nome tão feito, e é bom que você esteja preparado para um trabalho suado aqui. Em qualquer caso, lembre-se de que o preço a se pagar pelo conforto do po4a posteriormente. E o lado bom é que você só tem que fazer isso uma vez.

Em não consigo enfatizar isso muito. Para facilitar o processo, é, então, importante que você localize a versão exata que foi usada para a tradução. A melhor situação é quando você anotou a revisão no sistema de controle de versão usada para a tradução e não modificou o seu processo de tradução de forma que você possa usá-lo.

Vai funcionar melhor quando você usar um texto original atualizado com a tradução antiga. Ainda é possível, mas é mais difícil e realmente deveria ser evitado, se possível. Na verdade, creio que se você não conseguir localizar o texto original novamente, a melhor solução é localizar alguém para fazer a gettextização para você (mas, por favor, não eu ;).

Talvez eu esteja sendo muito dramático. Mesmo quando as coisas dão errado, ainda há formas mais rápidas do que traduzir tudo de novo. Eu consegui gettextizar a tradução para francês existente da documentação do Perl em um dia, mesmo as coisas tenham dado errado. Aquilo foi mais do que 2 megabytes de texto, e uma nova tradução demoraria meses ou mais.

Deixe-me explicar a base do procedimento primeiro e eu vou voltar com dicas para concluir quando o processo dá errado. Para facilitar a compreensão, vamos usar o exemplo acima novamente.

Assim que você tiver mestre.doc antigo novamente, o qual corresponde com a tradução XX.doc, a gettextização pode ser feita diretamente ao arquivo PO doc.XX.po sem tradução manual do arquivo tradução.pot:

 $ po4a-gettextize -f <formato> -m <mestre antigo.doc> -l <XX.doc> -p <doc.XX.po>

Quando você tiver sorte, é só isso. Você converteu sua tradução antiga para po4a e pode começar a tarefa de atualização agora mesmo. Basta seguir o procedimento explicado algumas seções atrás para sincronizar seu arquivo PO com o documento original mais novo e atualizar a tradução.

Por favor, note que mesmo quando as coisas parecem funcionar adequadamente, ainda há espaços para erros neste processo. A questão é que po4a não é capaz de entender o texto para certificar-se de que a tradução corresponde com o original. É por isso que todas as strings serão marcadas como "fuzzy" no processo. Você deveria verificar cada uma cuidadosamente antes de remover essas marcações.

Com frequência as estruturas do documento não correspondem exatamente, evitando po4a-gettextize de fazer seu trabalho adequadamente. A essa altura, o jogo em questão é sobre editar os arquivos para fazer com que suas estruturas correspondam.

Pode ser uma ajuda ler a seção Gettextização: como ela funciona? abaixo. Entender o processo interno pode ajudar você a fazer o seu trabalho. O lado positivo é que po4a-gettextize é bem detalhista sobre o que deu errado quando isso acontece. Primeiro, ele indica onde nos documentos há discrepância na estrutura. Você vai descobrir as strings que não correspondem, suas posições no texto e o tipo de cada uma delas. Mais ainda, o arquivo PO gerado será despejado para gettextization.failed.po.

-   Remove todas as partes extras das traduções, como as seções em que você informa o nome do tradutor e agradeço a todas as pessoas que contribuíram para a tradução. Adendos, que será descrito na próxima seção, vai permitir que você adicione-os posteriormente.

-   Não hesite em editar ambos o original e a tradução. A coisa mais importante é obter o arquivo PO. Você poderá atualizá-lo posteriormente. Isto posto, a edição da tradução deveria ser preferida quando pode-se fazer as duas coisas, pois ela facilita quando a gettextização tiver concluída.

-   Se necessário, mate algumas partes do original se elas não tiverem sido traduzidas; Ao se sincronizar do PO com o documento posteriormente, elas vão voltar por conta própria.

-   Se você alterou a estrutura um pouco (para mesclar dois parágrafos ou dividir outro), desfaça aquelas alterações. Se há problemas no original, você deveria informar o autor original. A correção deles na sua tradução resolve somente uma parte da comunidade. E além disso, isso é impossível quando se está usando po4a ;)

-   Algumas vezes, o conteúdo do parágrafo não corresponde, mas seus tipos não. Corrigir isso é até dependente do formato. No POD e man, frequentemente ele vem do fato que um dos dois contém uma linha começando com espaço em branco, mas a outra não. Naqueles formatos, tal parágrafo não pode ser dimensionado e, então, se torna um tipo diferente. Basta remover o espaço e está terminado. Pode ser um erro de escrita no nome da marcação.

    Likewise, two paragraphs may get merged together in POD when the separating line contains some spaces, or when there is no empty line between the =item line and the content of the item.

-   Algumas vezes, há uma dessincronização entre os arquivos e a tradução é anexada ao parágrafo original incorreto. Isso é um sinal de que o problema real é de antes nestes arquivos. Verifique gettextization.failed.po para ver quando começa a dessincronização e corrija-a lá.

-   Algumas vezes, você tem a sensação de que po4a comeu parte do texto, seja do original seja da tradução. gettextization.failed.po indica que ambos correspondem gentilmente e, então, a gettextização falha porque ele tentou corresponder um parágrafo com outro após (ou antes) do correto, como se o correto tivesse desaparecido. Xingue po4a como eu fiz quando isso aconteceu comigo. Generosamente.

    Essa situação infeliz acontece quando o mesmo parágrafo é repetido no documento. Nesse caso, nenhuma nova entrada é criada no arquivo PO, mas uma nova referência é adicionada ao já existente.

    So, when the same paragraph appears twice in the original but both are not translated in the exact same way each time, you will get the feeling that a paragraph of the original disappeared. Just kill the new translation. If you prefer to kill the first translation instead when the second one was actually better, remove the second one from where it is and put the first one in the place of the second one.

    Do contrário, se dois parágrafos similares, mas diferentes, foram traduzidos na mesma forma, você terá a sensação de que um parágrafo da tradução desapareceu. Uma solução é adicionar a estúpida da string ao parágrafo original (do tipo "Sou diferente"). Não tenha medo, aquelas coisas vão desaparecer durante a sincronização e quando o texto adicionar for curto o suficiente, gettext vai corresponder sua tradução ao texto existente (marcando-o como incerto, mas você não se importa se considerar que todas strings estarão marcadas como incertas após a gettextização).

Com muita esperança, essas dicas vão ajudar você a fazer sua gettextização funcionar e obter seu precioso arquivo PO. Agora você está pronto para sincronizar seu arquivo e começar sua tradução. Por favor, note que em um texto largo, pode acontecer de a primeira sincronização demorar um bom tempo.

Por exemplo, o primeiro po4a-updatepo da tradução para francês da documentação do Perl (arquivo PO de 5.5 MB) levou cerca de dois dias completos em um computador G5 de 1GHz. Sim, 48 horas. Mas os subsequentes demora apenas algumas dezenas de segundos no meu laptop antigo. Isso acontece porque na primeira vez, a maioria do msgid do arquivo PO não corresponde a qualquer dos arquivos POT. Isso força o gettext a pesquisar pelos mais próximos usando um custoso algoritmo de proximidade de strings.

  COMO adicionar um texto extra às traduções (ex.: nome do tradutor)?
Por causa da abordagem do gettext, fazer isso se torna mais difícil em po4a do que era quando simples edição de um novo arquivo junto com o original, Mas isso ainda é possível, graças aos famosos adendos.

Pode ajudar a compreensão considerar os adendos como uma espécie de patches aplicados ao documento localizado após processamento. Eles são meio que diferentes dos patches comuns (eles têm apenas uma linha de contexto, o que pode embutir expressões regulares de Perl, e podem adicionar apenas novos textos sem remover algum), mas as funcionalidades são as mesmas.

Seu objetivo é permitir que o tradutor adicione conteúdo extra ao documento que não está traduzido a partir do documento original. O uso mais comum é adicionar uma seção sobre a tradução em si, listando contribuidores e explicando como relatar um erro da tradução.

Um adendo deve ser fornecido em um arquivo separado. A primeira linha constitui em um cabeçalho indicando onde no documento produzido ele deveria ser colocado. O resto do arquivo de adendo será adicionado literalmente à posição determinada do documento resultante.

O cabeçalho possui uma sintaxe bem rígida: ele deve começar com a string PO4A-HEADER:, seguida por um uma lista separada por ponto-e-vírgula (;) de campos chave=valor. Espaços em branco SÃO importantes. Note que se você não puder usar o caractere ponto-e-vírgula (;) no valor e colocar entre aspas não vai ajudar.

Novamente, pode soar assustador, mas os exemplos dados abaixo deve ajudar você a descobrir como escrever a linha de cabeçalho que você precisa. Para ilustrar a discussão, suponha que nós queremos adicionar uma seção chamada "Sobre esta tradução" após a de "Sobre este documento".

Arqui estão as chaves de cabeçalho possíveis:

position (obrigatório)
    uma regexp (expressão regular). O adendo será colocado perto da linha correspondendo a esta regexp. Note que estamos falando do documento traduzido aqui, e não do original. Se mais do que uma linha corresponder a esta expressão (ou nenhuma), a adição vai falhar. É realmente melhor relatar um erro do que inserir um adendo na localização incorreta.

    Esta linha é chamada de ponto de posição a seguir. O ponto onde o adendo é adicionado é chamado de ponto de inserção. Esses dois pontos estão perto um do outro, mas não são iguais. Por exemplo, se você quer inserir uma nova seção, é fácil colocar o ponto de posição no título da seção precedente e explicar para o po4a onde a seção termina (lembre-se de que ponto de posição é dado por uma regexp que deveria corresponder a uma única linha).

    A localização do ponto de inserção no que se refere ao ponto de posição é controlada pelos campos mode, beginboundary e endboundary, como explicado abaixo.

    No nosso caso, não teríamos:

         position=<title>Sobre esse documento</title>

mode (obrigatório)
    Pode ser tanto a string before quanto after, especificando a posição do adendo, relativa ao ponto de posição.

    Já que nós queremos que a nova seção seja colocada abaixo daquela que estamos correspondendo, nós temos:

         mode=after

beginboundary (usado somente quando mode=after e obrigatório neste caso)
endboundary (idem)
    regexp correspondendo ao fim da seção após a qual o adendo entra.

    Quando mode=after, o ponto de inserção está após o ponto de posição, mas não diretamente após! É colocado no final da seção começando com o ponto de posição, isto é, após ou antes da linha ter correspondido ao argumento ???boundary, dependendo de se você usou beginboundary ou endboundary.

    No nosso caso, nós podemos escolher indicar o fim da seção que nós correspondemos ao adicionar:

       endboundary=</section>

    ou indicar o começo da próxima seção ao indicar:

       beginboundary=<section>

    Em ambos casos, nosso adendo vai ser localizado após </section> e antes de <section>. O primeiro é melhor já que ele vai funcionar mesmo se o documento for reorganizado.

    Ambas formas existem porque os formatos de documentação são diferentes. em alguns deles, há uma forma de marcar o fim da seção (como o </section> que nós usamos), enquanto alguns outros não marcam explicitamente o fim da seção (como no man). No primeiro caso, nós queremos fazer um boundary correspondendo ao fim da seção, de forma que o ponto de inserção venha após este. No segundo caso, nós queremos fazer um boundary correspondendo o começo da próxima seção, de forma que o ponto de inserção venha logo antes dele.

Isso pode parecer obscuro, mas esperamos que os próximos exemplos sejam mais claros.

Para resumir o exemplo usado até agora, para adicionar uma seção chamada "Sobre esta tradução" após a de "Sobre esta documentação" em um documento SGML, você pode usar qualquer uma das linhas de cabeçalho:
     PO4A-HEADER: mode=after; position=Sobre este documento; endboundary=</section>
     PO4A-HEADER: mode=after; position=Sobre este documento; beginboundary=<section>

Se você quiser adicionar alguma coisa após a seção nroff a seguir:
      .SH "AUTHORS"

    você deveria colocar uma position correspondendo a esta linha e um beginboundary correspondendo ao começo da próxima seção (isto é,, ^\.SH). O adendo vai, então, ser adicionado após o ponto de posição e imediatamente antes da primeira linha correspondendo ao beginboundary. Isso é dizer:

     PO4A-HEADER:mode=after;position=AUTHORS;beginboundary=\.SH

Se você quiser adicionar alguma coisa a uma seção (como após "Copyright Grande Cara") ao invés de adicionar uma seção inteira, forneça um position correspondendo a esta linha e forneça um beginboundary correspondendo a qualquer linha.
     PO4A-HEADER:mode=after;position=Copyright Grande Cara, 2004;beginboundary=^

Se você quiser adicionar alguma coisa ao final do documento, forneça um position correspondendo a qualquer linha do seu documento (mas apenas uma linha. Po4a não vai proceder se ela não for única), e forneça um endboundary correspondendo a nada. Não use strings simples aqui como "EOF", e sim prefira aquelas que possuem menos chance de estar no seu documento.
     PO4A-HEADER:mode=after;position=<title>Sobre</title>;beginboundary=FakePo4aBoundary

Em qualquer caso, lembre-se que essas são regexp. Por exemplo, se você quiser corresponder o fim de uma seção de nroff finalizando com a linha

  .fi

não use .fi como endboundary porque ele vai corresponder a "the[ fi]le", o que obviamente não é o que está esperando. O endboundary correto neste caso é: ^\.fi$.

Se o adendo não for onde você esperava, tente passar o argumento -vv para as ferramentas, de forma que elas expliquem a você o que estão fazendo enquanto inserem o adendo.

Exemplo mais detalhado

Documento original (formatado em POD):

 |=head1 NAME
 |
 |dummy - a dummy program
 |
 |=head1 AUTHOR
 |
 |me

Então, o adendo a seguir vai assegurar que a seção (em Francês) sobre o tradutor seja adicionado ao final do arquivo. (em Francês, "TRADUCTEUR" significa "TRADUTOR", e "moi" significa "eu")

 |PO4A-HEADER:mode=after;position=AUTEUR;beginboundary=^=head
 |
 |=head1 TRADUCTEUR
 |
 |moi

Para colocar seu adendo antes do AUTHOR, use o seguinte cabeçalho:

 PO4A-HEADER:mode=after;position=NOM;beginboundary=^=head1

Isso funciona porque a próxima linha correspondendo ao beginboundary /^=head1/ após a seção "NAME" (traduzido para "NOM" em Francês) é aquela declarando os autores. Então, o adendo será colocado entre as duas seções.

  COMO fazer tudo isso em uma invocação de programa?
O uso do po4a provou ser um pouco propenso a erros para usuários considerando que você tem que chamar dois programas diferentes na ordem correta (po4a-updatepo e então po4a-translate), cada um deles precisando de mais do que 3 argumentos. Além disso, era difícil com este sistema usar apenas um arquivo PO para todos os seus documentos quando mais de um formato era usado.

O programa po4a(1) foi projetado para resolver essas dificuldades. Assim que seu projeto tiver sido convertido para o sistema, você escreve um simples arquivo de configuração explicando onde seus arquivos de tradução estão (PO e POT), onde os documentos originais estão, seus formatos e onde suas traduções devem ser colocadas.

Então, ao chamar po4a(1) com este arquivo assegura que os arquivos PO são sincronizados com o documento original e que os documentos traduzidos sejam gerados adequadamente. É claro que você vai querer chamar este programa duas vezes: uma antes da edição do arquivo PO para atualizá-los e mais uma vez em seguida para obter um documento traduzido completamente atualizado. Mas você só precisa se lembrar de uma linha de comando.

  COMO personalizar o po4a?
Módulos do po4a possuem opções (especificadas com a opção -o) que podem ser usadas para alterar o comportamento do módulo.

Também é possível personalizar um módulo ou módulos novos / derivados / modificados ao colocar um módulo em lib/Locale/Po4a/ e adicionar lib aos caminhos especificados pelo ambiente PERLLIB ou PERL5LIB. Por exemplo:

   PERLLIB=$PWD/lib po4a --previous po4a/po4a.cfg

Nota: o nome real do diretório lib não é importante.

Como ele funciona?
Este capítulo dá a você uma visão geral da parte interna do po4a, de forma que você pode se sentir mais confiante para nos ajudar a manter e melhorá-lo. ele também pode ajudá-lo a entender o porquê de ele não funcionar da forma que você esperava, e como resolver seus problemas.

  Qual é a jogada aqui?
A arquitetura do po4a é orientada a objeto (em Perl. Isso não é legal?). O antepassado comum para todas as classes analisadoras é chamado de TransTractor. Esse nome estranho vem do fato que ele é ao mesmo tempo o encarregado por tradução de documento e extração de strings.

Mais formalmente, ele pega um documento para traduzir mais um arquivo PO contendo as traduções para usar como entrada, enquanto produz duas saídas separadas: outro arquivo PO (resultante da extração das strings traduzíveis do documento de entrada) e um documento traduzido (com a mesma estrutura daquele de entrada, mas com todas as strings traduzíveis substituídas com o conteúdo do PO de entrada). Aqui está uma representação gráfica disso:

   Doc. de entrada --\                             /---> Doc. de saída
                      \      TransTractor::       /       (traduzido)
                       +-->--   parse()  --------+
                      /                           \
   PO de entrada ----/                             \---> PO de saída
                                                           (extraído)

Esse pequeno osso é o núcleo de toda arquitetura do po4a. Se você omitir o PO de entrada e o documento de saída, você obtém po4a-gettextize. Se você fornecer ambos arquivos de entrada e desconsiderar o PO de saída, você obtém po4a-translate.

TransTractor::parse() é uma função virtual implementada por cada módulo. Aqui está um pequeno exemplo para mostrar a você como ela funciona. Ela analisa uma lista de parágrafos, um de cada vez com <p>.

  1 sub parse {
  2   PARAGRAPH: while (1) {
  3     $my ($paragraph,$pararef,$line,$lref)=("","","","");
  4     $my $first=1;
  5     while (($line,$lref)=$document->shiftline() && defined($line)) {
  6       if ($line =~ m/<p>/ && !$first--; ) {
  7         $document->unshiftline($line,$lref);
  8
  9         $paragraph =~ s/^<p>//s;
 10         $document->pushline("<p>".$document->translate($paragraph,$pararef));
 11
 12         next PARAGRAPH;
 13       } else {
 14         $paragraph .= $line;
 15         $pararef = $lref unless(length($pararef));
 16       }
 17     }
 18     return; # Não conseguiu uma linha definida? Fim do arquivo de entrada.
 19   }
 20 }

Na linha 6, nós encontramos <p> pela segunda vez. Esse é o sinal de próximo parágrafo. Nós deveríamos, então, colocar a linha que acabamos de obter de volta no documento original (linha 7) e jogar o parágrafo adquirido até agora para as saídas. Após remover o <p> do começo do parágrafo na linha 9, nós realizamos a concatenação dessa marcação com a tradução do resto do parágrafo.

Essa função translate() é muito legal. Ela joga o argumento para o arquivo PO de saída (extração) e retorna sua tradução da forma como encontrada no arquivo PO de entrada (tradução). Considerando que é usada como parte do argumento de pushline(), essa tradução acaba dentro do documento de saída.

Isso não é legal? É possível compilar um módulo po4a completo em menos de 20 segundos quando o formato é simples o suficiente...

Você pode aprender mais sobre isso en Locale::Po4a::TransTractor(3pm).

  Gettextização: como ela funciona?
A ideia aqui é pegar o documento original e sua tradução, e dizer que a enésima string extraída da tradução é a tradução da enésima string extraída do original. Para que isso funcione, ambos arquivos devem compartilhar exatamente a mesma estrutura. Por exemplo, se os arquivos possui a estrutura a seguir, é improvável que a 4ª string na tradução (do tipo "capítulo") seja a tradução da 4ª string no original (do tipo "parágrafo").

    Original           Tradução

  capítulo           capítulo
    parágrafo          parágrafo
    parágrafo          parágrafo
    parágrafo        capítulo
  capítulo              parágrafo
    parágrafo          parágrafo

Para isso, analisadores po4a são usados em ambos arquivos original e tradução para extrair arquivos PO e, então, um terceiro arquivo PO é compilado deles pegando as mensagens do segundo como tradução das strings do primeiro. Para confirmar que as strings que nós colocamos juntas são realmente as traduções de cada um, os analisadores de documento no po4a deveria colocar informação sobre o tipo sintático das strings extraídas do documento (todos existentes fazem isso, os seus devem fazer também). Então, essa informação é usada para certificar-se de que ambos documentos possuem a mesma sintaxe. O exemplo anterior, ele nos permitiria detectar que a string 4 é um parágrafo em um caso, e no outro é um título de capítulo e relatar o problema.

Em teoria, seria possível detectar o problema e sincronizar novamente os arquivos em seguida (assim como o diff faz). Mas o que nós deveríamos fazer com as poucas strings antes da dessincronização não é muito claro, e isso poderia produzir resultados indesejáveis em algumas situações. É por isso que a implementação atual não tenta sincronizar novamente e falha com detalhes quando alguma coisa dá errado, exigindo modificação manual dos arquivos para corrigir o problema.

Mesmo com essas precauções, coisas podem dar errado facilmente aqui. É por isso que todas as traduções presumidas dessa forma são marcadas como incertas, para certificar de que o tradutor reveja e verifique-as.

  Adendo: como ele funciona?
Bom, isso é bem simples. O documento traduzido não é escrito diretamente, mas é mantido na memória até que os adendos são aplicados. Os algoritmos envolvidos são até que simples. Nós procuramos por uma linha correspondendo a posição da regexp e inserimos o adendo antes, se estivermos em mode=before. Se não, nós procuramos pela próxima linha correspondendo à fronteira ("boundary") e insere o adendo após a linha, se ele for um endboundary, ou antes dessa linha, se ele for um beginboundary.

FAQ
Este capítulo agrupa as perguntas frequentes (FAQ). Na verdade, a maioria das perguntas até agora puderam ser formuladas dessa forma: "Porque ele é projetado dessa forma e não dessa outra?" Se você pensa que po4a não é a resposta correta para tradução de documentação, você deveria considerar ler esta seção. Se ele não responder suas perguntas, por favor entre em contato conosco na lista de discussão <po4a-devel@lists.alioth.debian.org>. Nós adoramos feedback.

  Por que traduzir cada parágrafo separadamente?
Sim, no po4a, cada parágrafo é traduzido separadamente (na verdade, cada módulo decide isso, mas todos os módulos existentes fazem isso, e o seu deveria também). Há muitas vantagens nesta abordagem:

•   Quando as partes técnicas do documento estão ocultas da cena, o tradutor não pode bagunçá-las. Quanto menos marcadores nós mostrarmos para o tradutor, menos erro ele pode criar.

•   Cortar o documento ajuda a isolar as alterações do documento original, localizando quais partes da tradução precisam ser atualizadas para facilitar esse processo.

Mesmo com essas vantagens, algumas pessoas não gostam da ideia de traduzir cada parágrafo separadamente. Aqui estão algumas respostas que eu posso dar para o seus medo:

•   Essa abordagem foi provada com sucesso no projeto KDE e permite que as pessoas produzam o maior corpo de documentação traduzida e atualizada que eu conheço.

•   Os tradutores ainda podem usar o contexto para traduzir, já que as strings no arquivo PO estão na mesma ordem que no documento original. Traduzir sequencialmente é, então, comparável se você sua po4a ou não. E, em qualquer caso, a melhor forma de obter o contexto está em converter o documento para um formato imprimível, já que o formatadores de texto não são realmente legíveis, na minha opinião.

•   Essa abordagem é uma das usadas por tradutores profissionais. Nós concordamos que eles têm objetivos meio diferentes dos tradutores de código aberto. A manutenção é, por exemplo, normalmente menos crítica para eles, já que o conteúdo raramente é alterado.

  Por que não dividir a nível de sentença (ou menor)?
Ferramentas dos tradutores profissionais de alguma forma dividem o documento a nível de sentença para obter o máximo de reusabilidade das traduções antigas e para agilizar seu processo. O problema é que a mesma sentença pode ter várias traduções, dependendo do contexto.

Parágrafos são por definição maiores que as sentenças. Isso vai assegurar que mantendo o mesmo parágrafo em dois documentos vai haver o mesmo sentido (e tradução), independente do contexto de cada caso.

Divisão em partes menores do que a sentença seria muito ruim. Demoraria um pouco explicar o porquê aqui, mas o leitor interessado pode ver o página de manual do Locale::Maketext::TPJ13(3pm) (a qual vem com a documentação do Perl), por exemplo. Resumindo, cada idioma tem suas próprias regras sintáticas e não é possível criar sentenças agregando de partes de sentenças de forma que funcione para todos os idiomas existentes (ou até mesmo para as 5 das 10 mais falados, ou até menos).

  Why not put the original as comment along with translation (or the other way around)?
À primeira vista, gettext não parece estar adaptado para todos os tipos de traduções. Por exemplo, ele não parecia adaptado para debconf, a interface que todos os pacotes Debian usamo para sua interação com o usuário durante a instalação. Neste caso, os textos para traduzir eram bem pequeno (umas dúzias de linhas para cada pacote) e era difícil colocar a tradução em um arquivo especializado, já que ele tinha que estar disponível antes da instalação do pacote.

É por isso que o desenvolvedor do debconf decidiu implementar outra solução, na qual traduções estariam localizadas no mesmo arquivo que o original. Isso até que é atraente. Alguém poderia até querer fazer isso para XML, por exemplo. Se pareceria essa forma:

 <section>
  <title lang="en">My title</title>
  <title lang="fr">Mon titre</title>

  <para>
   <text lang="en">My text.</text>
   <text lang="fr">Mon texte.</text>
  </para>
 </section>

Mas isso era tão problemático que uma abordagem baseada em PO é usada no momento. Apenas o original pode ser editado no arquivo e as traduções devem ser feitas nos arquivos PO extraídos do modelo mestre (e colocadas de volta na hora de compilar o pacote). O sistema antigo estava obsoleto porque possuía diversos problemas:

•   problemas de manutenção

    Se vários tradutores fornecessem um patch ao mesmo tempo, ficava difícil mesclá-los.

    Como você vai detectar alterações no original ao qual precisam ser aplicadas as traduções? Para poder usar diff, você tem que anotar qual versão do original você traduzido, isto é, você precisa de um arquivo PO no seu arquivo ;)

•   problemas de codificação

    Essa solução é viável quando somente idiomas europeus estão envolvidos, mas a tradução de coreano, russo e/ou árabe realmente complica a situação. UTF seria uma solução, mas ainda haveria problemas nessa questão.

    Além disso, tais problemas são difíceis de detectar (isto é, somente leitores coreanos vão detectar que a codificação em coreano está quebrada [por causa do tradutor russo])

gettext resolve todos os problemas ao mesmo tempo.

  Mas gettext não foi projetado para esse uso!
É verdade, mas até agora ninguém veio com uma solução melhor. E a única alternativa conhecida é a tradução manual, com todos os problemas de manutenção.

  E as outras ferramentas de tradução para documentação usando gettext?
Até onde eu sei, há somente duas:

poxml
    Essa é a ferramenta desenvolvida pelo pessoal do KDE para manipular DocBook XML. Até onde eu sei, esse foi o primeiro programa a extrair strings para traduzir de documentação para arquivos PO, e a injetá-las de volta após a tradução.

    Ela só consegue manipular XML e apenas um DTD em particular. Eu fico, particularmente, não gosto das listas de manipulação, que acabam com um grande msgid. Quando a lista fica grande, o fragmento se torna mais difícil de engolir.

po-debiandoc
    Esse problema desenvolvido por Denis Barbier é uma espécie de precursor do módulo de SGML do po4a, o qual meio que torna-o (po-debiandoc) obsoleto. Como o nome já diz, ele linda apenas o DebianDoc DTD, o qual é meio que um DTD obsoleto.

As principais vantagens do po4a sobre eles é a facilidade de adição de conteúdo extra (o que é bem pior lá) e a habilidade de alcançar gettextização.

  Educando desenvolvedores sobre tradução
Quando você tenta traduzir documentação ou programas, você lida com três tipos de problemas: linguísticas (nem todo mundo sabe 2 idiomas), técnicos (é por isso que po4a existe) e relacional/humano. Nem todos os desenvolvedores entendem a necessidade de traduzir as coisas. Mesmo quando estão com boa vontade, eles podem ignorar como facilitar o trabalho de tradutores. Para ajudar nisso, po4a vem com muita documentação que pode ser vista.

Outro ponto importante é que cada arquivo traduzido começa com um comentário curto, indicando que arquivo é e como usá-lo. Isso deve ajudar os coitados dos desenvolvedores mergulhados em toneladas de arquivos em diferentes idiomas que eles mal conhecem e os ajuda a lidar com isso corretamente.

No projeto po4a, documentos traduzidos não são arquivos fontes mais. Considerando que arquivos SGML são arquivos fontes habituais, isso é um erro fácil. É por isso que todos os arquivos possuem esse cabeçalho:

 |       *****************************************************
 |       *           GENERATED FILE, DO NOT EDIT             *
 |       * THIS IS NO SOURCE FILE, BUT RESULT OF COMPILATION *
 |       *****************************************************
 |
 | This file was generated by po4a-translate(1). Do not store it (in VCS,
 | for example), but store the PO file used as source file by po4a-translate.
 |
 | In fact, consider this as a binary, and the PO file as a regular source file:
 | If the PO gets lost, keeping this translation up-to-date will be harder ;)

Da mesma forma, arquivo PO comuns do gettext apenas precisam ser copiados para o diretório po/. Mas esse não é o caso daqueles manipulados por po4a. O maior risco aqui é um desenvolvedor apagar a tradução existente do seu programa com a tradução da sua documentação. (os dois não podem ser armazenados no mesmo arquivo PO, porque o programa precisa instalar sua tradução em um arquivo MO enquanto a documentação usa apenas sua tradução em tempo de compilação). É por isso que os arquivos PO produzidos pelo módulo po-debiandoc contêm o cabeçalho a seguir:

 #
 #  ADVISES TO DEVELOPERS:
 #    - you do not need to manually edit POT or PO files.
 #    - this file contains the translation of your debconf templates.
 #      Do not replace the translation of your program with this !!
 #        (or your translators will get very upset)
 #
 #  ADVISES TO TRANSLATORS:
 #    If you are not familiar with the PO format, gettext documentation
 #     is worth reading, especially sections dedicated to this format.
 #    For example, run:
 #         info -n '(gettext)PO Files'
 #         info -n '(gettext)Header Entry'
 #
 #    Some information specific to po-debconf are available at
 #            /usr/share/doc/po-debconf/README-trans
 #         or http://www.debian.org/intl/l10n/po-debconf/README-trans
 #

  RESUMO das vantagens da abordagem baseada em gettext

•   As traduções não são armazenadas junto do original, o que possibilita detectar se as traduções estão desatualizadas.

•   As traduções são armazenadas em arquivos separados um dos outros, o que previne tradutores de idiomas diferentes interferir tanto quando da submissão do patch quanto a nível de codificação do arquivo.

•   Ele é internamente baseado no gettext (mas po4a oferece uma interface bem simples, de forma que você não precisa entender as especificidades para usá-lo). Dessa forma, nós não temos que reinventar a roda e, por causa do seu amplo uso, nós podemos pensar que essas ferramentas meio que não tem erros.

•   Nada mudou para o usuário final (além do fato de traduções estarem melhor mantidas, espero). o arquivo de documentação resultante distribuído é exatamente o mesmo.

•   Não há necessidade de tradutores aprenderem um novo arquivo de sintaxe e seu editor de arquivos PO (como o modo PO do Emacs, Lokalize ou Gtranslator) vão funcionar muito bem.

•   gettext oferece uma forma simples de obter estatísticas sobre o que está feito, o que deveria ser revisto e atualizado e o que ainda deve ser feito. Alguns exemplos podem ser encontrados nesses endereços:

     - http://kv-53.narod.ru/kaider1.png
     - http://www.debian.org/intl/l10n/

Mas tudo tem seu lado negativo, e essa abordagem tem algumas desvantagens com as quais nós temos que lidar.

•   Adendos são... estranhos à primeira vista.

•   Você não pode adaptar o texto traduzido às suas preferências, com divisão de um parágrafo aqui e juntar outros dois ali. Mas de certa forma, se há um problema com o original, isso deveria ser relatado como um erro.

•   Até mesmo com uma interface fácil, ainda é uma nova ferramenta que as pessoas precisam aprender.

    Um dos meus sonhos seria integrar de alguma forma po4a ao Gtranslator ou Lokalize. Quando um arquivo SGML fosse aberto, as strings seriam automaticamente extraídas. Quando um arquivo SGML traduzido fosse salvo, poderia ser gravado no disco. Se nós conseguirmos fazer um módulo para MS Word (TM) (ou pelo menos RTF), tradutores profissionais podem até mesmo usá-lo.

AUTORES
 Denis Barbier <barbier,linuxfr.org>
 Martin Quinson (mquinson#debian.org)