Pular para o conteúdo principal

Como o Sync Funciona

O comando sync é a principal operação do rosetta. Aqui está o que acontece quando você executa npx i18n-rosetta sync.

Visão Geral do Pipeline

Passo a Passo

1. Resolução de Configuração

O rosetta carrega o i18n-rosetta.config.json (ou detecta as configurações automaticamente). Ele resolve:

  • Localidade de origem e localidades de destino
  • O grafo de pares (quais combinações origem→destino processar)
  • Configurações de método, modelo e qualidade por par

Antes de escanear os arquivos, o rosetta imprime um cabeçalho de inicialização:

i18n-rosetta v3.3.2

[INFO] Detected format: json (auto)
[INFO] Detected framework: Hugo
  • Banner de versão: Mostra a versão instalada para depuração e relatórios de problemas.
  • Detecção de formato: Informa o formato do arquivo e se ele foi detectado automaticamente (auto) ou configurado explicitamente (config). Suporta json, toml e yaml.
  • Detecção de framework: Quando contentDir está definido, identifica o framework (Hugo) para confirmar que a sincronização de conteúdo está ativa.

2. Escaneamento da Origem

O arquivo de localidade de origem é carregado e transformado em um mapa plano de chave→valor:

// Input (nested)
{ "hero": { "title": "Welcome", "subtitle": "Build" } }

// Flattened
{ "hero.title": "Welcome", "hero.subtitle": "Build" }

3. Detecção de Alterações

O rosetta lê o .i18n-rosetta.lock, que armazena os hashes SHA-256 dos valores de origem traduzidos anteriormente. Para cada chave, ele verifica:

CondiçãoAção
Chave ausente no destinoTraduzir
Hash de origem alterado desde o último syncRetraduzir (desatualizado)
Valor de destino começa com [EN]Retraduzir (marcador de fallback legado)
Hash de origem inalterado, chave existeIgnorar

É por isso que o rosetta traduz apenas o que mudou — ele não retraduz o arquivo inteiro a cada sincronização.

4. Agrupamento em Lotes

As chaves são agrupadas em lotes (padrão: 80 chaves/lote para LLM, 128 para o Google Translate). O agrupamento em lotes reduz as idas e vindas da API, mantendo os prompts gerenciáveis.

Durante a tradução, o rosetta exibe uma barra de progresso na mesma linha que é atualizada após a conclusão de cada lote:

[INFO] fr.json — 2,847 missing
████████████████░░░░░░░░░░░░░░░░ 1,440/2,847 keys

A barra é renderizada usando o retorno de carro (carriage return) \r para atualizações no mesmo lugar — sem rolagem de tela. Suprimida nos modos --quiet e --json.

4b. Memória de Tradução

Antes do agrupamento em lotes, o rosetta verifica o cache da Memória de Tradução (.rosetta/tm.json). Chaves cujo texto de origem + localidade + método correspondem a uma tradução anterior são servidas instantaneamente do cache — nenhuma chamada de API é necessária.

[TM] 142 key(s) served from cache
Translating 3 key(s) to French (llm)... [OK]

A TM (Memória de Tradução) é o principal mecanismo de economia de custos. Executar o sync novamente após a alteração de uma única chave traduz apenas essa chave, não o arquivo inteiro. Veja Memória de Tradução para mais detalhes.

Para ignorar o cache em uma única execução: i18n-rosetta sync --no-tm

5. Tradução

Cada lote é enviado para o método de tradução configurado:

  • llm: Prompt estruturado para o OpenRouter com instruções de registro e orientação de gênero
  • llm-coached: O mesmo, mas com regras gramaticais, dicionário e notas de estilo injetados
  • google-translate: Requisição em lote para a Google Cloud Translation API v2
  • api: HTTP POST para um endpoint remoto

A mensagem do sistema (registro, orientação de gênero, regras) é idêntica em todos os lotes para uma determinada localidade, permitindo o cache de prompt — provedores como Anthropic e Google fazem cache de mensagens de sistema repetidas, reduzindo os custos de tokens.

6. Quality Gate (Controle de Qualidade)

Toda tradução é validada antes de ser gravada no disco. Cinco verificações são executadas:

VerificaçãoO que ela detectaExemplo
Vazio/em brancoO modelo não retornou nada""
Eco da origemO modelo retornou a entrada em inglês"Welcome" para japonês
Loop de alucinaçãoTrigramas repetidos"Qo' Qo' Qo' Qo'"
Inflação de tamanhoA saída é 4×+ maior que a origemOrigem de 10 carac. → Saída de 50 carac.
Conformidade de escritaSistema de escrita errado para a localidadeTexto latino para localidade árabe

As falhas são registradas com um prefixo [GATE]. Sem fallbacks silenciosos.

Veja Quality Gate para mais detalhes.

6b. Verificação de Terminologia

Para pares treinados (coached) com um dicionário, o rosetta verifica se o LLM realmente usou a terminologia exigida após a tradução. As violações são registradas como avisos [TERM]:

[TERM] en→fr: 2 term violation(s)
• "dashboard" → expected "tableau de bord" but got "panneau"

Estes são avisos, não erros de bloqueio — a tradução ainda é gravada.

7. Cascata de Novas Tentativas (Retry Cascade)

Em caso de falha na análise (parse) do JSON ou erros no nível do lote, o rosetta tenta novamente com lotes progressivamente menores:

Full batch (80 keys) → Failed
└→ Half batch (40 keys) → 1 failure
└→ Individual keys (1 each) → Isolates the problem key

O orçamento de novas tentativas é limitado por maxRetries (padrão: 3) para evitar gastos descontrolados com tokens.

8. Gravação e Bloqueio (Write & Lock)

As traduções aprovadas são gravadas no arquivo de localidade de destino, preservando a estrutura de aninhamento original. O arquivo de bloqueio (lock file) é atualizado com os novos hashes SHA-256.

9. Verificação

Após todos os pares serem processados, o rosetta relê os arquivos de localidade gravados no disco e executa uma passagem de verificação (a menos que --no-verify esteja definido). Isso captura a lacuna entre o sync relatar sucesso e as chaves estarem de fato erradas:

  • Paridade de chaves — todas as chaves de origem presentes em cada destino
  • Marcadores de fallback [EN] — marcadores legados de execuções anteriores
  • Traduções vazias — valores em branco que passaram despercebidos
  • Conformidade de escrita — localidades não latinas com traduções apenas em ASCII
  • Preservação de placeholders — placeholders ICU correspondem à origem
  • Problemas de codificação — marcadores BOM, caracteres invisíveis

Isso também está disponível como um comando i18n-rosetta verify autônomo para gates de CI.

Tradução de Conteúdo (Fase 2)

Para projetos Docusaurus e Hugo, o sync executa uma segunda fase após a tradução das chaves JSON. Esta fase traduz arquivos Markdown e MDX (documentação, posts de blog, tutoriais) usando os mesmos métodos e quality gate.

Como funciona

  1. O rosetta descobre todos os arquivos de conteúdo de origem (.md, .mdx) percorrendo o diretório content/docs
  2. Para cada par arquivo × localidade, ele verifica um arquivo de bloqueio de conteúdo separado (.i18n-rosetta-content.lock) em busca de alterações de hash SHA-256
  3. Arquivos alterados ou ausentes são coletados em um pool plano de itens de trabalho
  4. O pool é processado com simultaneidade paralela (padrão: 12 chamadas de API simultâneas)
Phase 2: content (79 translations to process, 341 skipped, concurrency: 48)

[1/79] (1%) docs/concepts/security.md → ja [RE-TRANSLATE] (~3328s left)
[2/79] (3%) docs/concepts/security.md → th [RE-TRANSLATE] (~1821s left)
...
[79/79] (100%) blog/v3-2-quality.md → de [OK]

[OK] Created 79 content file(s), 341 unchanged

Paralelismo

Tanto a Fase 1 (chaves JSON) quanto a Fase 2 (conteúdo) agora são executadas em paralelo:

  • Fase 1: Todas as traduções de localidade são disparadas simultaneamente (padrão: 50 localidades simultâneas). Dentro de cada localidade, os lotes de API também são executados em paralelo (4 lotes simultâneos). Uma sincronização de 12 localidades com 120 chaves é concluída em ~1 minuto em vez de ~15 minutos.
  • Fase 2: Todas as combinações arquivo×localidade são traduzidas como um pool plano (padrão: 12 chamadas de API simultâneas). Arquivos diferentes e localidades diferentes são traduzidos simultaneamente.

Controle o paralelismo com --json-concurrency, --content-concurrency ou --concurrency (define ambos):

# Faster JSON sync (more parallel locale translations)
npx i18n-rosetta sync --json-concurrency 30

# Faster content sync (more parallel API calls)
npx i18n-rosetta sync --content-concurrency 20

# Slower (gentler on rate limits)
npx i18n-rosetta sync --concurrency 4

Proteção de conteúdo

Durante a tradução, o rosetta protege o conteúdo não traduzível:

  • Blocos de código (delimitados e recuados) são substituídos por placeholders
  • Campos de Frontmatter que não estão na lista translatableFields são preservados como estão
  • Links, caminhos de imagens e tags HTML são protegidos
  • Shortcodes e variáveis de interpolação (ex., {count}, {{.Params.title}}) são protegidos

Após a tradução, todos os placeholders são restaurados e validados. Se algum estiver ausente ou corrompido, a tradução é rejeitada e tentada novamente.

Sucesso Parcial

Um lote que falhou não bloqueia o restante. Se 9 de 10 lotes forem bem-sucedidos, esses 9 serão gravados. O lote que falhou é registrado no log, e você pode executar sync novamente para tentar outra vez.

Execução Simulada (Dry Run)

Visualize o que mudaria sem gravar nenhum arquivo:

npx i18n-rosetta sync --dry-run

Forçar Retradução

Force a retradução de chaves específicas, mesmo se não tiverem sido alteradas:

npx i18n-rosetta sync --force-keys "hero.title,nav.about"

Estimativa de Custos

Antes de traduzir, o rosetta gera um relatório de custos pré-sync mostrando os custos estimados por par. Isso é executado automaticamente durante cada sync — você o vê antes que qualquer chamada de API seja feita.

╔══════════════════════════════════════════════════════════╗
║ Cost Estimate ║
╠════════════╦═══════╦════════════╦════════════════════════╣
║ Pair ║ Keys ║ Est. Cost ║ Method ║
╠════════════╬═══════╬════════════╬════════════════════════╣
║ en → fr ║ 142 ║ $0.07 ║ google-translate ║
║ en → ja ║ 38 ║ — ║ llm (model-dependent) ║
║ en → crk ║ 38 ║ — ║ llm-coached ║
╚════════════╩═══════╩════════════╩════════════════════════╝

O Que é Estimado

Cada método de tradução fornece sua própria estimativa de custo:

MétodoBase de CustoPrecisão
google-translateTaxa publicada do Google (US$ 20/milhão de caracteres)Precisa
llmVaria de acordo com o modelo do OpenRouterDependente do modelo — verifique os preços do OpenRouter
llm-coachedO mesmo que llm mais tokens de contexto de treinamento (coaching)Dependente do modelo
apiDeterminado pelo servidorDesconhecida — não é possível estimar sem consultar o endpoint

Quando um método não consegue determinar o custo (métodos LLM, APIs remotas), o rosetta relata em vez de adivinhar. Use --dry para ver as estimativas de custo sem realmente traduzir.


Veja Também