Ir para o conteúdo

Guias

Trabalhar com tradutores

Os seus catálogos são JSON simples, sem nada proprietário para converter. Isso te dá três formas de traduzir: entregar os arquivos a um TMS, ir e voltar com arquivos de tradutor usando export/import, ou traduzir à máquina com translate.

JSON plano, sem lock-in

A maioria dos TMS (Crowdin, Lokalise, Phrase e companhia) lê catálogos JSON de forma nativa. Você aponta a plataforma para locales/ e está feito: sem passo de exportação e sem formato próprio. As traduções voltam nos mesmos arquivos, e cada alteração se revê como um diff normal.

Export para humanos

Quando não há TMS (um tradutor freelance, uma agência, um colega com uma planilha), o verbaly export escreve um arquivo pronto para tradução por idioma, com o texto original ao lado de cada tradução. Se você guarda seu catálogo por grupos, ele exporta uma linha por mensagem, nomeada com seu caminho completo, então o tradutor vê texto e nunca um grupo.

npx verbaly export                   # verbaly-export/es.xlf, pt.xlf (XLIFF 2.0)
npx verbaly export --format csv      # key,source,target,location (any spreadsheet)
npx verbaly export --format po       # es.po, pt.po (gettext, any PO editor)
npx verbaly export --missing         # only what's untranslated

XLIFF 2.0 é o formato de intercâmbio da indústria, por isso os TMS e as ferramentas CAT abrem-no diretamente. Os seus espaços e etiquetas viajam lá como fichas protegidas com nomes com sentido, por isso um tradutor não as pode quebrar sem querer; as palavras de plural e de select ficam editáveis, porque essas têm mesmo de ser traduzidas. Gettext PO funciona com o Poedit e com qualquer ferramenta de PO, e CSV é para todos os outros, editável em qualquer lado. Todos os formatos dizem onde vive cada texto na sua origem, por isso o tradutor vê o contexto em vez de o adivinhar.

Antes de exportar, verbaly status mostra quanto falta por idioma: es: 45/48 translated (94%).

Import de volta, validado

verbaly import lê os arquivos traduzidos (XLIFF 2.0 ou 1.2, CSV ou gettext PO) e preenche seus catálogos. Cada entrada passa pela mesma validação estrutural da tradução por máquina: placeholders, variantes de plural e tags devem sobreviver intactos. O resto é rejeitado e reportado, nunca escrito.

npx verbaly import verbaly-export/es.xlf
#   es: +42 imported
#   es: 1 rejected (params/tags not preserved): home.greeting
npx verbaly import es.csv --dry-run    # preview without writing
npx verbaly import es.xlf --overwrite  # replace existing translations
npx verbaly import es.xlf --draft      # keep it as drafts until someone reads it

As traduções existentes são mantidas a menos que você passe --overwrite; keys desconhecidas são ignoradas e reportadas. Entradas que uma ferramenta PO marca como fuzzy contam como não traduzidas. O idioma de destino vem do próprio arquivo (ou do nome do arquivo), e --locale vence os dois. Ele é lido como um dos seus idiomas, então o pt_BR do gettext preenche o seu pt-BR. Um idioma novo começa o seu catálogo com o código bem escrito, a menos que a sua config liste os seus locales: aí um idioma fora dessa lista é pulado com um aviso e código de saída 1, já que o seu app nunca o carregaria. Passe --draft quando ninguém leu o arquivo ainda: o que ele traz fica marcado como rascunho até alguém aprovar.

A rede de segurança, em palavras simples

Editar locales/es.json à mão é uma forma perfeitamente válida de traduzir, e recebe a mesma proteção de um arquivo importado. verbaly check lê cada tradução ao lado do original e falha quando a tradução não consegue dizer a mesma coisa, e cada build a lista. Você não precisa lembrar destas regras: se quebrar uma, o erro diz qual e onde.

Quando alguém muda um texto fonte, as traduções dele não ficam como se nada tivesse acontecido. O Verbaly registra para qual texto fonte uma tradução foi escrita no momento em que ela é escrita, seja por um provedor, um agente, o Studio ou um arquivo importado, e a marca como desatualizada assim que esse texto muda, até ser atualizada, ou mantida com verbaly review --approve quando ainda diz a coisa certa. O arquivo de um tradutor traz o texto fonte de onde partiu, então um arquivo traduzido de uma versão anterior fica desatualizado assim que chega. Editar uma tradução tira a marca sozinha.

npx verbaly status é a olhada rápida: quanto está traduzido por idioma, quanto espera revisão, quanto está desatualizado e quanto está quebrado.

Exportar para apps mobile

Os mesmos catálogos podem viajar para um app mobile irmão como recursos nativos: android-xml escreve pastas strings.xml que você solta em res/, e ios-strings escreve pastas .lproj para o Xcode.

npx verbaly export --format android-xml   # verbaly-export/values-es/strings.xml, values-pt-rBR/…
npx verbaly export --format ios-strings   # verbaly-export/es.lproj/Localizable.strings, …

Seu idioma fonte vira o padrão da plataforma (values/strings.xml, en.lproj), e chaves sem tradução ficam de fora para o app fazer fallback a ele em vez de mostrar texto vazio. As keys são adaptadas a nomes de recurso válidos do Android, os valores mantêm sua sintaxe de parâmetros intacta, e o fluxo é de mão única: as traduções vão dos seus catálogos para o app.

Ainda sem humanos disponíveis?

A tradução por máquina preenche as lacunas com as mesmas garantias estruturais, e tudo o que um provider ou uma pessoa errar é pego pelo verbaly check no CI.

A saída da máquina chega marcada como rascunho: o translate registra o que escreveu em verbaly.lock, ao lado da sua config. Como o lockfile de um gerenciador de pacotes, o Verbaly o escreve, você o commita com seus catálogos e ninguém o edita à mão, então ninguém confunde a saída da máquina com trabalho revisado. Se um merge deixá-lo com um conflito, o Verbaly mantém os rascunhos dos dois lados e o próximo extract o escreve inteiro: inclua-o no commit do merge. Apagá-lo marcaria todos os rascunhos como revisados.

npx verbaly translate            # es: +12 translated (draft)
npx verbaly review               # list what's waiting for a human
npx verbaly review --approve     # accept after reading
npx verbaly check --drafts       # CI gate: fail while drafts remain

Antes da primeira execução, escreva o que não se traduz. Os nomes do seu produto, os das suas funções e qualquer forma que você já tenha decidido vão em translate.glossary, e como você trata o leitor vai em translate.instructions. Sai mais barato do que corrigir a mesma palavra à mão depois de cada execução.

Uma execução longa sobrevive a uma conexão ruim. As requisições que falham por algo passageiro são tentadas de novo, e se ainda assim uma não voltar, todo o resto fica salvo e o relatório nomeia as mensagens que não conseguiu preencher. Rodar translate de novo pede só essas, então uma execução interrompida nunca custa tudo duas vezes. Também não custa o trabalho de ninguém: uma mensagem que alguém salvou enquanto a execução estava fora mantém o seu texto, e o relatório diz quantas deixou como estavam.

O verbaly review lista o que espera, rascunhos da máquina e traduções escritas para um texto fonte anterior, cada um com o texto que é publicado ao lado da sua tradução. verbaly review --approve aceita depois de ler, seguido de chaves quando você quer aceitar só essas, e um arquivo de tradutor trazido com import conta como revisão por si só. No CI, verbaly check --drafts continua falhando enquanto restarem rascunhos sem revisar, e --outdated enquanto restar uma tradução desatualizada.

Um agente de código pode rodar esse mesmo ciclo através do servidor MCP: o que ele traduzir continua chegando como rascunho atrás da mesma porta de revisão, inclusive as traduções que ele mesmo escrever.

↑↓para navegarEnterpara abrir
Copiado para a área de transferência