Trovare le chiavi mancanti nei file ARB di un'app Flutter

Aggiornato il · LocalePilot

Una chiave aggiunta in inglese e dimenticata in tedesco, un placeholder rinominato in una sola lingua: sono errori che compilano senza problemi e finiscono davanti ai tuoi utenti. Ecco come intercettarli prima del rilascio.

Hai fretta? Controlla i tuoi file ARB direttamente nel browser: gratis, senza registrazione, niente viene caricato.

Breve ripasso: come sono organizzati i file ARB

Con flutter gen-l10n, ogni lingua ha il proprio file (app_en.arb, app_fr.arb…). Il file template, impostato da template-arb-file in l10n.yaml, è il riferimento: contiene tutte le chiavi e i relativi metadati @key (descrizione, placeholder).

{
  "cartCount": "{count, plural, =0{Empty cart} =1{1 item} other{{count} items}}",
  "@cartCount": {
    "placeholders": { "count": { "type": "int" } }
  }
}

1. Lascia che Flutter elenchi i messaggi non tradotti

Aggiungi l'opzione untranslated-messages-file a l10n.yaml:

arb-dir: lib/l10n
template-arb-file: app_en.arb
untranslated-messages-file: untranslated.json

A ogni generazione, Flutter scrive in quel file le chiavi del template mancanti in ogni lingua. È il controllo più semplice da impostare; assicurati che il file sia vuoto (o contenga solo {}) prima di pubblicare.

2. Confronta le chiavi con un piccolo script Dart

Per un controllo in CI che fallisca in modo chiaro, basta uno script:

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();

Le chiavi che iniziano con @ sono metadati, quindi vengono escluse dal confronto.

3. Controlla i placeholder

Una chiave presente ovunque può comunque rompersi: se la traduzione francese usa {nombre} mentre il template dichiara {count}, gen-l10n aggiunge nombre come parametro in più in tutte le locale, e le chiamate esistenti smettono di compilare. Al contrario, una traduzione che perde semplicemente un placeholder passa senza alcun avviso (dettagli nella guida su plurali e placeholder ICU). Per ogni chiave, confronta i nomi tra graffe con quelli dichiarati in @key.placeholders. Attenzione ai messaggi ICU (plural, select): parole chiave come other non sono placeholder.

4. Tieni d'occhio anche i valori vuoti

Alcuni flussi di traduzione creano la chiave con un valore vuoto finché non viene tradotta. Non risulta "mancante", quindi aggiungi un controllo che segnali le stringhe vuote in ogni lingua tranne il template.

Checklist prima del rilascio

  • Il file dei messaggi non tradotti è vuoto.
  • Ogni lingua ha le stesse chiavi del template.
  • I placeholder corrispondono, chiave per chiave.
  • Nessun valore vuoto fuori dal template.
  • I messaggi lunghi sono stati verificati a schermo nelle lingue più prolisse (il tedesco, per esempio).

Domande frequenti

Flutter segnala le traduzioni mancanti?

Sì, se aggiungi untranslated-messages-file a l10n.yaml: flutter gen-l10n vi elenca le chiavi del template mancanti in ogni lingua. Senza, ottieni solo un avviso riassuntivo.

Devo copiare i metadati @key in ogni lingua?

No. I metadati (descrizione, placeholder) vengono letti dal file template; gli altri file contengono solo le traduzioni.

Come evito placeholder con il nome sbagliato?

Per ogni chiave, confronta i nomi tra graffe nella traduzione con quelli dichiarati nel template, e fai fallire la CI quando sono diversi.