runSyncTranslations function

Future<void> runSyncTranslations()

Implementation

Future<void> runSyncTranslations() async {
  print('๐Ÿš€ Starting localization sync...\n');

  await loadFilters();

  if (await hasUncommittedChanges()) {
    print(
      'โš ๏ธ Uncommitted changes detected in Git. Please commit or stash before running this script.',
    );
    exit(1);
  }

  const enPath = 'assets/translations/en-US.json';
  const arPath = 'assets/translations/ar-SA.json';
  const newKeysFile = 'new_keys_for_translation.txt';

  print('๐Ÿ“‚ Scanning presentation layer files...');
  final dartFiles = Directory('lib/features')
      .listSync(recursive: true)
      .where((f) => f.path.contains('presentation') && f.path.endsWith('.dart'))
      .toList();
  print('โœ… Found ${dartFiles.length} Dart files\n');

  final snakeCaseRegex = RegExp(r'''["']([a-z0-9_]+)["']''');
  final keys = <String>{};

  print('๐Ÿงน Sanitizing and updating keys in Dart files...');
  for (final file in dartFiles) {
    String content = await File(file.path).readAsString();
    bool modified = false;

    final matches = snakeCaseRegex.allMatches(content).toList();

    for (final m in matches) {
      final original = m.group(1)!;

      if (shouldSkip(original)) continue;

      final safe = KeySanitizer.makeDartSafeKey(original);

      if (safe != null && safe != original) {
        final quotedOriginal = m.group(0)!;
        final quoteChar = quotedOriginal[0];
        final quotedSafe = '$quoteChar$safe$quoteChar';
        content = content.replaceAll(quotedOriginal, quotedSafe);
        modified = true;
      }

      if (safe != null) {
        keys.add(safe);
      }
    }

    if (modified) {
      await File(file.path).writeAsString(content);
    }
  }
  print('โœ… Dart files updated\n');

  print('๐Ÿ“– โœ… Validate & Normalize Json Files...');
  await validateAndNormalizeJsonKeys(File(enPath), File(arPath));

  print('๐Ÿ“– Updating $enPath...');
  final file = File(enPath);
  Map<String, dynamic> data = {};

  if (await file.exists()) {
    data = json.decode(await file.readAsString());
  }

  bool updated = false;
  final newEntries = <String, String>{};

  for (var key in keys) {
    if (!data.containsKey(key)) {
      final humanReadable = toHumanReadable(key);
      data[key] = humanReadable;
      newEntries[key] = humanReadable;
      updated = true;
    }
  }

  if (updated) {
    final encoder = JsonEncoder.withIndent('  ');
    await file.writeAsString(encoder.convert(data));
    print('โœ๏ธ Updated $enPath\n');

    print('๐Ÿ“ Exporting new keys for translation...');
    final buffer = StringBuffer();
    buffer.writeln(
      '# Please translate the following English phrases into Arabic and keep the keys unchanged.\n',
    );
    buffer.write(JsonEncoder.withIndent('  ').convert(newEntries));
    await File(newKeysFile).writeAsString(buffer.toString());
    print('๐Ÿ“„ Exported $newKeysFile\n');

    await runEasyLocalizationGenerate();
  } else {
    print('โœ… No changes needed for $enPath\n');
  }

  print('๐ŸŽ‰ Done! All localization keys are up to date.');
}