Ir para o conteúdo

Guias

Trabalhar com tradutores

Seus catálogos são JSON plano, sem nada proprietário para converter. Isso te dá três caminhos para traduzir: entregar os arquivos a um TMS, fazer round-trip de arquivos de tradutor com export/import, ou traduzir por máquina com translate.

JSON plano, sem lock-in

A maioria dos TMS (Crowdin, Lokalise, Phrase e companhia) ingere JSON plano nativamente. Aponte a plataforma para locales/ e pronto: sem etapa de export, sem formato próprio. As traduções voltam como os mesmos arquivos, e cada mudança é revisada 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, então TMS e ferramentas CAT o abrem direto, e seus placeholders e tags viajam nele como fichas protegidas com nomes com sentido, então um tradutor não consegue quebrá-los por acidente (as palavras de plural e select seguem editáveis: essas sim se traduzem). Gettext PO funciona com Poedit e qualquer ferramenta PO. CSV é para todo o resto: editável em qualquer lugar. Todos os formatos dizem onde cada texto vive no seu código, então o tradutor vê o contexto em vez de 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

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.

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 para o build quando a tradução não consegue dizer a mesma coisa. Você não precisa lembrar destas regras: se quebrar uma, o erro diz qual e onde.

npx verbaly status é a olhada rápida: quanto está traduzido por idioma, quanto espera revisão 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 locales/.verbaly-drafts.json, commitado com seus catálogos e nunca editado à mão, então ninguém confunde com trabalho revisado.

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.

O verbaly review lista o que espera, verbaly review --approve aceita depois de ler, 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.

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.

Copiado para a área de transferência