Com pressa? Verifique seus arquivos ARB direto no navegador: grátis, sem cadastro, nada é enviado.
Como os arquivos ARB são organizados
Com o flutter gen-l10n, cada idioma tem seu próprio arquivo (app_en.arb, app_fr.arb…). O arquivo template, definido por template-arb-file no l10n.yaml, é a referência: ele contém todas as chaves e seus metadados @key (descrição, placeholders).
{
"cartCount": "{count, plural, =0{Empty cart} =1{1 item} other{{count} items}}",
"@cartCount": {
"placeholders": { "count": { "type": "int" } }
}
}
1. Deixe o Flutter listar as mensagens não traduzidas
Adicione a opção untranslated-messages-file ao l10n.yaml:
arb-dir: lib/l10n
template-arb-file: app_en.arb
untranslated-messages-file: untranslated.json
A cada geração, o Flutter grava nesse arquivo as chaves do template que faltam em cada idioma. É a verificação mais simples de configurar; confira se o arquivo está vazio (ou contém apenas {}) antes de publicar.
2. Compare as chaves com um pequeno script Dart
Para uma verificação de CI que falhe de forma clara, um script basta:
import 'dart:convert';
import 'dart:io';
void main() {
final dir = Directory('lib/l10n');
final template = _keys(File('lib/l10n/app_en.arb'));
var failed = false;
for (final file in dir.listSync().whereType<File>()) {
if (!file.path.endsWith('.arb')) continue;
final missing = template.difference(_keys(file));
if (missing.isNotEmpty) {
failed = true;
print('${file.path}: ${missing.join(', ')}');
}
}
if (failed) exit(1);
}
Set<String> _keys(File f) => (jsonDecode(f.readAsStringSync()) as Map<String, dynamic>)
.keys
.where((k) => !k.startsWith('@'))
.toSet();
As chaves que começam com @ são metadados, por isso ficam fora da comparação.
3. Verifique os placeholders
Uma chave presente em todos os idiomas ainda pode quebrar: se a tradução francesa usa {nombre} enquanto o template declara {count}, o gen-l10n adiciona nombre como parâmetro extra em todos os locales, e as chamadas existentes deixam de compilar. Por outro lado, uma tradução que simplesmente perde um placeholder passa sem nenhum aviso (detalhes no guia de plurais e placeholders ICU). Para cada chave, compare os nomes entre chaves com os declarados em @key.placeholders. Atenção às mensagens ICU (plural, select): palavras-chave como other não são placeholders.
4. Fique de olho também nos valores vazios
Alguns fluxos de tradução criam a chave com um valor vazio até ela ser traduzida. Ela não aparece como "ausente", então adicione uma verificação que aponte strings vazias em todos os idiomas, exceto no template.
Checklist antes do lançamento
- O arquivo de mensagens não traduzidas está vazio.
- Todos os idiomas têm as mesmas chaves que o template.
- Os placeholders batem, chave por chave.
- Nenhum valor vazio fora do template.
- As mensagens longas foram conferidas na tela nos idiomas mais extensos (alemão, por exemplo).