Ir para o conteúdo

Referência

CLI

O comando verbaly vive em @verbaly/compiler. Adicione-o às suas dependências de desenvolvimento para que npx verbaly funcione: os gestores de pacotes só ligam um comando de um pacote que você mesmo instalou, e os plugins dependem do compilador sem o instalar por você.

Comandos

13 comandos, na ordem em que o ciclo os usa. Cada um leva à sua seção.

Scaffolding

verbaly init deixa o projeto pronto em um comando: uma config tipada (.ts se você tem tsconfig, .mjs se não), o seu catálogo fonte mais um por --locales, e os próximos passos conforme o que ele encontrar: Astro, Nuxt, Next.js, SvelteKit e Vite têm cada um a sua integração, e qualquer outro bundler usa @verbaly/unplugin.

npx verbaly init --locales es,pt
  1. created: verbaly.config.ts, locales/en.json, locales/es.json, locales/pt.json
  2. detected: vite
  3. next steps: pnpm add -D @verbaly/vite

Reexecutar é seguro: uma config ou catálogo existente é reportado como “kept” e fica intacto.

Checagem de saúde

verbaly doctor é o irmão do init para projetos já rodando: inspeciona todo o setup e reporta cada achado com o comando exato que o corrige. Verde significa saudável; problemas saem com 1.

npx verbaly doctor
  1. Correto config: verbaly.config.ts found
  2. Correto catalogs: 3 locales (en, es, pt) in locales/
  3. Correto plugin: @verbaly/vite installed for vite
  4. Aviso types: verbaly.d.ts is stale fix: run npx verbaly extract
  5. Aviso orphans: 2 catalog keys are no longer referenced (old.title, hero.cta) fix: run npx verbaly extract --prune to drop them
  6. Erro imports: 1 file imports t from a verbaly package, which never exports it (src/app.ts) fix: t comes from your instance (React: const t = useT()) or from virtual:verbaly
  7. Erro translations: 1 broken translation (es): present but not rendering what the source renders fix: run npx verbaly check to read what each one lost

Um comando para responder “porque é que isto não traduz?” Verifica a tua config e os teus catálogos, se está instalada a integração que o teu framework precisa, se o verbaly.d.ts está atualizado, as chaves órfãs e a saúde das tuas traduções: as que faltam, as quebradas e os avisos. Também apanha duas coisas que o gate da build não consegue ver: t importado de um pacote do verbaly, que nenhum bundler resolve, e uma mensagem que ficou com um bloco plural ou de formato como texto literal. Também nomeia qualquer ficheiro que não conseguiu analisar, como aviso: os seus textos não são extraídos, mas o ficheiro pode compilar na mesma no teu projeto. Um relatório saudável significa uma build que passa: o doctor falha em tudo o que o check falha, mais falhas de setup como essas duas, e nunca em algo que compila e renderiza.

Envolver texto fixo

verbaly wrap encontra texto fixo no seu JSX e o envolve em t`…` por você. Primeiro informa, e --write aplica. O que for ambíguo é listado para um humano em vez de adivinhado, e um ficheiro onde t não está disponível fica intacto e é informado, então o projeto continua sempre a compilar.

npx verbaly wrap           # report what it would wrap
npx verbaly wrap --write   # apply it

Passar de outra biblioteca

verbaly migrate passa os catálogos que já tens. O teu ficheiro mantém a forma, aninhada ou plana, e a única coisa que tem de reescrever é a interpolação: {{name}} passa a {name}, porque uma chaveta duplicada é como o Verbaly escreve uma chaveta literal. Primeiro reporta, e --write aplica.

npx verbaly migrate             # report what it would port
npx verbaly migrate --write     # apply it
npx verbaly migrate --plurals --write   # and merge _one/_other

--plurals é a metade opcional: junta _one e _other numa só mensagem com variantes, que é o que dá a seleção de plural automática, e lá dentro o número escreve-se já localizado. Também percebe a forma antiga key + key_plural. Sem a flag, essas keys continuam a funcionar tal como estão.

O que não vai adivinhar fica listado: um formato do i18next dentro das chavetas, um valor {{- sem escape}}, um aninhamento com $t(), e uma junção que apagaria uma key que já usas. Essas mensagens ficam exatamente como estavam.

Extração

verbaly extract analisa o seu código (.js/.ts/.jsx/.tsx, mais .svelte, .vue e .astro), escreve as mensagens novas no catálogo de origem, acrescenta marcadores "" ao resto e regenera o verbaly.d.ts. Avisa quando uma mensagem ficou com um bloco plural ou de formato como texto literal, e nomeia qualquer ficheiro que não conseguiu analisar em vez de parar nele.

npx verbaly extract           # sync catalogs + types
npx verbaly extract --prune   # and drop keys nothing references

Cobertura

verbaly status mostra num relance quanto está traduzido por idioma (es: 45/48 translated), quantas traduções automáticas ainda esperam revisão e quantas estão quebradas. É apenas informativo e nunca falha; --json entrega os mesmos números a badges e ferramentas.

npx verbaly status          # es: 45/48 translated
npx verbaly status --json   # the same numbers, for badges and tooling

Pseudo-localização

verbaly pseudo preenche um catálogo de QA (en-XA por padrão) a partir do locale fonte: letras acentuadas, marcadores ⟦…⟧ e ~33% de padding. Texto que sai limpo no build pseudo está hardcoded; layouts que cortam se revelam antes de uma tradução real.

npx verbaly pseudo                 # locales/en-XA.json
# "Hello {name}" → "⟦Ĥéĺĺó {name} ~⟧"

Params, blocos de variantes e tags sobrevivem verbatim, garantido pela mesma validação estrutural do translate. Re-executar regenera o catálogo completo.

Tradução de máquina

verbaly translate fecha o ciclo: escrever → extracttranslatecheck verde. O provider padrão usa Claude (@anthropic-ai/sdk como peer opcional + ANTHROPIC_API_KEY); batches de 20 por request, cada um dizendo ao modelo em quais arquivos fonte o texto vive, então ele traduz com contexto.

npx verbaly translate --dry-run        # list what's missing, write nothing
npx verbaly translate --locales es,pt  # fill only these locales
npx verbaly translate --model claude-opus-4-8  # override the default (claude-sonnet-5)

Cada tradução é verificada: os placeholders e as tags precisam sobreviver intactos. Se um não sobrevive, a tradução é rejeitada e a entrada fica em "", então o check continua sinalizando até você corrigir.

Sem lock-in: conecte seu próprio provider no verbaly.config.ts. Em TypeScript, TranslateProvider tipa ele para você, e origins diz em quais arquivos do código cada texto aparece, então você traduz pensando no lugar onde ele é usado:

verbaly.config.ts
import type { TranslateProvider } from '@verbaly/compiler';

const provider: TranslateProvider = async ({ sourceLocale, targetLocale, messages, origins }) => ({
  /* key → translation */
});

export default { translate: { provider } };

Revise os rascunhos

A saída da máquina é um rascunho, não trabalho revisado. O translate registra tudo o que escreve em locales/.verbaly-drafts.json (commitado com seus catálogos, nunca editado à mão), e o verbaly review fecha o ciclo: leia os rascunhos e aprove.

npx verbaly review               # es: x7Ka9q2f, hero.title (2 awaiting review)
npx verbaly review --approve     # accept after reading
npx verbaly check --drafts       # CI gate: fail while drafts remain

Quer bloquear o merge até um humano assinar? Adicione --drafts ao check do seu CI: ele continua falhando enquanto restarem traduções por máquina sem revisar. Um arquivo de tradutor trazido com import conta como revisão por si só.

Tradutores e TMS

Humanos no ciclo? verbaly export escreve arquivos XLIFF 2.0, CSV ou gettext PO por idioma prontos para o tradutor e verbaly import os traz de volta, validados estruturalmente com o mesmo gate do translate. O fluxo completo, opções de TMS incluídas, vive em Trabalhar com tradutores.

verbaly import valida cada entrada, e rejeita e informa as quebradas. Entradas PO marcadas como fuzzy contam como não traduzidas, e as chaves importadas deixam de contar como rascunhos sem revisar.

O export também escreve recursos nativos de mobile: --format android-xml para a estrutura res/ do Android e --format ios-strings para o Xcode. As keys sem tradução ficam de fora para o app cair no seu idioma fonte (--missing vale só para os formatos de tradutor). Todos os formatos escrevem em verbaly-export/ a menos que você aponte --out para outro lugar.

O que o gate verifica

check faz duas perguntas, não uma. Cada mensagem está traduzida? E cada tradução consegue mostrar o que o original mostra? Uma tradução preenchida não é automaticamente uma que funciona, então isto também para o build, venha de onde vier: de uma pessoa, de uma máquina ou de uma edição à mão.

A traduçãoPor que falha
perdeu um {param}, ou mudou o nome deleo valor nunca chega ao texto
perdeu um <em>, ou ganhou uma ênfase ou a marca do link desaparece
transformou um bloco de plural em texto simplesuma única redação para qualquer quantidade
tem um bloco de plural sem o caso othercada quantidade que não lista aparece vazia

Dois achados são avisos: eles aparecem, o código de saída continua em 0, porque o texto ainda é mostrado. Um é um plural sem as formas que o idioma precisa, já que polonês e árabe pedem mais que o inglês. O outro é um caso específico como =0 que o original tinha e a tradução deixou de fora, então essa quantidade agora cai em other.

Seja qual for a falha, o relatório fecha com o passo que a repara: gerar e preencher quando uma mensagem ainda não tem tradução, corrigir a key quando ela não vive em nenhum catálogo, e consertar a própria mensagem quando ela está quebrada.

Exemplo de CI

.github/workflows/ci.yml
- run: pnpm install
- run: npx verbaly check --reporter github   # each finding becomes a PR annotation
- run: pnpm build

Com --reporter github cada achado aparece como anotação no pull request, apontando para o arquivo e a linha onde o texto vive: os erros como erros, os avisos como avisos, então um aviso nunca deixa o job vermelho. Sem isso você recebe a lista em texto simples, com o mesmo código de saída.

Renderização estática (SSG)

verbaly render mata o piscar de texto por traduzir em sites estáticos: percorre o teu HTML construído e preenche cada elemento data-verbaly por idioma usando o runtime a sério: plurais, formatação com Intl, data-verbaly-args, tradução de atributos e texto rico da whitelist. Dentro de um idioma, os links para páginas que esse idioma também tem mantêm o seu prefixo, por isso quem lá chega fica lá. Levá-lo até lá é o --redirect, mais abaixo.

npx vite build              # or astro build, eleventy, …
npx verbaly render          # dist/index.html filled in the source locale
                            # dist/es/index.html, dist/pt/… for the rest
npx verbaly render --site out --locales es  # custom dir / locale filter

Flags

FlagDefaultDescrição
--rootcwdRaiz do projeto
--dirlocalesDiretório de catálogos
--sourceenIdioma fonte
--localesdos arquivosIdiomas extras, separados por vírgula
--pruneoffRemove chaves sem referências (só no extract)
--watchoffRe-extrai quando os arquivos fonte mudam: extração viva para setups com webpack, Rspack e Rollup (só extract)
--localeen-XAId do pseudo-locale (só pseudo)
--sitedistDiretório do site compilado (só render)
--baseraiz do siteSubcaminho onde o site é servido (só render)
--redirectoffManda para o seu idioma quem chega à página inicial (só render)

As flags são validadas por comando: uma flag que pertence a outro comando termina com um erro acionável em vez de ser ignorada em silêncio: translate --locale es avisa que você queria --locales.

Arquivo de config

As flags vencem verbaly.config.{js,mjs,ts,mts,json} na raiz do projeto, e o plugin recebe as mesmas opções. Todas elas, com o seu valor padrão, vivem em Configuração.

Agentes de código

Seu agente de código pode rodar esse mesmo ciclo sem tocar no terminal, através do servidor @verbaly/mcp. Esse canal tem página própria. Agentes de código cobre o servidor, suas ferramentas e recursos, a Agent Skill instalável e o índice llms.txt que este site serve.

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