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.
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.
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.
- Mantenha cada
{placeholder}, escrito igual. É o espaço onde entra um nome, uma quantidade ou uma data. Traduza as palavras ao redor, nunca a de dentro. - Mantenha as tags em pares.
<em>…</em>e companhia marcam ênfase ou um link. Mova para onde a frase precisar, mas não deixe uma metade de fora. Palavras que só parecem uma tag são suas para traduzir: emPress <Enter> to continuenada fecha esse sinal, então nada está checando isso. - Mantenha o bloco de plural como bloco de plural, e conserve sempre o caso
other. Esse caso é o curinga: sem ele, qualquer quantidade que você não listou não mostra nada. - Adicione as formas que o seu idioma precisa. O inglês se resolve com duas, o polonês e o árabe precisam de mais. Verbaly avisa quais faltam, e esse aviso é um conselho, não uma falha.
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.
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.
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.