Jak znaleźć brakujące klucze w plikach ARB aplikacji Flutter

Zaktualizowano · LocalePilot

Klucz dodany po angielsku i zapomniany po polsku, placeholder przemianowany tylko w jednym języku: takie błędy się kompilują i trafiają do użytkowników. Oto jak wyłapać je przed wydaniem.

Spieszysz się? Sprawdź pliki ARB od razu w przeglądarce: za darmo, bez rejestracji, nic nie jest wysyłane.

Krótkie przypomnienie: jak zorganizowane są pliki ARB

Z flutter gen-l10n każdy język ma własny plik (app_en.arb, app_pl.arb…). Plik szablonu, ustawiony przez template-arb-file w l10n.yaml, jest wzorcem: zawiera wszystkie klucze i ich metadane @key (opis, placeholdery).

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

1. Niech Flutter wypisze nieprzetłumaczone komunikaty

Dodaj opcję untranslated-messages-file do l10n.yaml:

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

Przy każdym generowaniu Flutter zapisuje w tym pliku klucze szablonu, których brakuje w każdym języku. To najprostsza kontrola do wdrożenia; przed wydaniem upewnij się, że plik jest pusty (albo zawiera tylko {}).

2. Porównaj klucze małym skryptem w Dart

Jeśli kontrola w CI ma kończyć się wyraźnym błędem, wystarczy taki skrypt:

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

Klucze zaczynające się od @ to metadane, więc są wyłączone z porównania.

3. Sprawdź placeholdery

Klucz obecny wszędzie wciąż może się zepsuć: jeśli polskie tłumaczenie używa {liczba}, a szablon deklaruje {count}, gen-l10n dodaje liczba jako dodatkowy parametr we wszystkich lokalizacjach, a istniejące wywołania przestają się kompilować. I odwrotnie: tłumaczenie, które po prostu gubi placeholder, przechodzi bez żadnego ostrzeżenia (szczegóły w poradniku o liczbie mnogiej i placeholderach ICU). Dla każdego klucza porównaj nazwy w nawiasach klamrowych z zadeklarowanymi w @key.placeholders. Uważaj na komunikaty ICU (plural, select): słowa kluczowe takie jak other nie są placeholderami.

4. Pilnuj też pustych wartości

Niektóre procesy tłumaczeniowe tworzą klucz z pustą wartością, dopóki nie zostanie przetłumaczony. Nie pojawia się on jako „brakujący”, więc dodaj kontrolę, która wskazuje puste teksty we wszystkich językach poza szablonem.

Lista kontrolna przed wydaniem

  • Plik nieprzetłumaczonych komunikatów jest pusty.
  • Każdy język ma te same klucze co szablon.
  • Placeholdery się zgadzają, klucz po kluczu.
  • Brak pustych wartości poza szablonem.
  • Długie komunikaty zostały sprawdzone na ekranie w najbardziej rozwlekłych językach (na przykład niemieckim czy polskim).

Najczęściej zadawane pytania

Czy Flutter zgłasza brakujące tłumaczenia?

Tak, jeśli dodasz untranslated-messages-file do l10n.yaml: flutter gen-l10n wypisuje tam klucze szablonu, których brakuje w każdym języku. Bez tego dostajesz tylko ogólne ostrzeżenie.

Czy muszę kopiować metadane @key do każdego języka?

Nie. Metadane (opis, placeholdery) są czytane z pliku szablonu; pozostałe pliki potrzebują tylko tłumaczeń.

Jak uniknąć źle nazwanych placeholderów?

Dla każdego klucza porównaj nazwy w nawiasach klamrowych w tłumaczeniu z zadeklarowanymi w szablonie i zatrzymaj CI, gdy się różnią.