Spanish is the app default (SFLocalizations.testInit uses 'es', localeResolutionCallback falls back to the first supported locale), so make that explicit by pointing the code generator at es.json instead of en.json. Regenerating picked up 12 activity-meter keys that were already present in every locale file but had drifted out of I18n. Add scripts/check_i18n_parity.dart: treats es.json as the template and reports any missing or orphan keys in en/fr/de/it/pt. Exits non-zero so it can gate CI or a pre-commit hook later.
73 lines
1.9 KiB
Dart
73 lines
1.9 KiB
Dart
// ignore_for_file: avoid_print
|
|
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
const _l10nDir = 'assets/l10n';
|
|
const _templateLocale = 'es';
|
|
const _otherLocales = ['en', 'fr', 'de', 'it', 'pt'];
|
|
|
|
void main() {
|
|
final templatePath = '$_l10nDir/$_templateLocale.json';
|
|
final templateFile = File(templatePath);
|
|
if (!templateFile.existsSync()) {
|
|
stderr.writeln('Template file not found: $templatePath');
|
|
stderr.writeln('Run this script from packages/sf_localizations/');
|
|
exit(1);
|
|
}
|
|
|
|
final templateKeys = _readKeys(templateFile);
|
|
print('Template ($_templateLocale.json): ${templateKeys.length} keys');
|
|
print('');
|
|
|
|
var hasErrors = false;
|
|
for (final locale in _otherLocales) {
|
|
final path = '$_l10nDir/$locale.json';
|
|
final file = File(path);
|
|
if (!file.existsSync()) {
|
|
print('$locale.json: MISSING FILE');
|
|
hasErrors = true;
|
|
continue;
|
|
}
|
|
|
|
final keys = _readKeys(file);
|
|
final missing = templateKeys.difference(keys);
|
|
final extra = keys.difference(templateKeys);
|
|
|
|
if (missing.isEmpty && extra.isEmpty) {
|
|
print('$locale.json: OK (${keys.length} keys)');
|
|
continue;
|
|
}
|
|
|
|
hasErrors = true;
|
|
print('$locale.json: MISMATCH');
|
|
if (missing.isNotEmpty) {
|
|
print(' Missing from $locale (${missing.length}):');
|
|
final sorted = missing.toList()..sort();
|
|
for (final k in sorted) {
|
|
print(' - $k');
|
|
}
|
|
}
|
|
if (extra.isNotEmpty) {
|
|
print(' Extra in $locale not in $_templateLocale (${extra.length}):');
|
|
final sorted = extra.toList()..sort();
|
|
for (final k in sorted) {
|
|
print(' + $k');
|
|
}
|
|
}
|
|
}
|
|
|
|
print('');
|
|
if (hasErrors) {
|
|
stderr.writeln('i18n parity check FAILED');
|
|
exit(1);
|
|
}
|
|
print('i18n parity check PASSED');
|
|
}
|
|
|
|
Set<String> _readKeys(File file) {
|
|
final content = file.readAsStringSync();
|
|
final map = json.decode(content) as Map<String, dynamic>;
|
|
return map.keys.toSet();
|
|
}
|