main function

void main()

Implementation

void main() async {
  final fallbackFile = File(
    path.join(
      getRootDirectory(),
      "lib",
      "translations",
      "translation_fallback.json",
    ),
  );
  if (!await fallbackFile.exists()) {
    throw Exception(
      "translation_fallback.json not found in lib/translations folder.",
    );
  }

  final fallbackJson = await fallbackFile.readAsString();
  final Map fallbackEntries = jsonDecode(fallbackJson);
  final translationFile = Translations.fromJson(fallbackEntries.cast());
  late String baseLanguageCode;

  final Map<String, StringBuffer> translationsBuffers = {};
  final baseBuffer = StringBuffer();
  final inMemoryBuffer = StringBuffer();
  final localizationCodes = <String>[];

  const importString = "import './base_localization.dart';";

  final grouppedTranslations =
      groupBy(translationFile.translations, (t) => t.languageCode);

  for (var i = 0; i < grouppedTranslations.keys.length; i++) {
    final key = grouppedTranslations.keys.elementAt(i);
    final translations = grouppedTranslations[key] ?? [];
    final first = i == 0;
    final buffer = StringBuffer();
    localizationCodes.add(translations[0].languageCode);
    if (first) {
      baseLanguageCode = grouppedTranslations.keys.first;
    }

    final missingTranslations =
        grouppedTranslations[baseLanguageCode]!.where((t) {
      return !translations.map((e) => e.code).contains(t.code);
    });
    translations.addAll(missingTranslations);

    for (var translation in translations) {
      final (:value, :plural, :none) = translation.extractVariables();

      if (first) {
        inMemoryBuffer.writeln("@override");
        baseBuffer.writeln(
          "/// **${translation.value.value}** on $baseLanguageCode language <br>",
        );
        if (translation.value.plural != null) {
          baseBuffer.writeln(
            "/// plural: **${translation.value.plural}** <br>",
          );
        }
        if (translation.value.none != null) {
          baseBuffer.writeln(
            "/// none: **${translation.value.none}** <br>",
          );
        }
        if (translation.value.singularOnly) {
          if (value.isEmpty) {
            inMemoryBuffer.writeln(
              "String get ${_cleanAttributeName(translation.code)} => map[language][\"${translation.code}\"]['value'];",
            );
            baseBuffer.writeln(
              "String get ${_cleanAttributeName(translation.code)};",
            );
          } else {
            inMemoryBuffer.writeln(
              "String ${_cleanAttributeName(translation.code)}({required ${value.map((e) => 'String $e').join(',')}}) => map[language][\"${translation.code}\"]['value'].${value.map((e) => 'replaceAll("{$e}",$e)').join('.')};",
            );
            baseBuffer.writeln(
              "String ${_cleanAttributeName(translation.code)}({required ${value.map((e) => 'String $e').join(',')}});",
            );
          }
        } else {
          final args = <String>{...value, ...plural, ...none};
          args.remove("count");
          if (args.isEmpty) {
            inMemoryBuffer.writeln(
              "String ${_cleanAttributeName(translation.code)}(int count) => count == 1 ? map[language][\"${translation.code}\"]['value'] :  count == 0 ? map[language][\"${translation.code}\"]['none'] : map[language][\"${translation.code}\"]['plural'];",
            );
            baseBuffer.writeln(
              "String ${_cleanAttributeName(translation.code)}(int count);",
            );
          } else {
            inMemoryBuffer.writeln(
              "String ${_cleanAttributeName(translation.code)}({required int count, ${args.map((e) => 'required String $e').join(',')}}) => (count == 1 ? map[language][\"${translation.code}\"]['value'] :  count == 0 ? map[language][\"${translation.code}\"]['none'] : map[language][\"${translation.code}\"]['plural']).${value.map((e) => 'replaceAll("{$e}",$e)').join('.')}.replaceAll('{count}',count.toString());",
            );
            baseBuffer.writeln(
              "String ${_cleanAttributeName(translation.code)}({required int count, ${args.map((e) => 'required String $e').join(',')}});",
            );
          }
        }
      }

      buffer.writeln("@override");
      if (translation.value.singularOnly) {
        if (value.isEmpty) {
          buffer.writeln(
            "String get ${_cleanAttributeName(translation.code)} => \"${translation.value.value}\";",
          );
        } else {
          buffer.writeln(
            "String ${_cleanAttributeName(translation.code)}({${value.map((e) => 'required String $e').join(',')}}) => \"${translation.value.value}\".${value.map((e) => 'replaceAll("{$e}",$e)').join('.')};",
          );
        }
      } else {
        final args = <String>{...value, ...plural, ...none};
        args.remove("count");
        if (args.isEmpty) {
          buffer.writeln(
            "String ${_cleanAttributeName(translation.code)}(int count) => (count ==0 ? \"${translation.value.none}\" : count == 1 ? \"${translation.value.value}\" : \"${translation.value.plural}\").replaceAll('{count}',count.toString());",
          );
        } else {
          buffer.writeln(
            "String ${_cleanAttributeName(translation.code)}({required int count, ${args.map((e) => 'required String $e').join(',')}}) => (count ==0 ? \"${translation.value.none}\" : count == 1 ? \"${translation.value.value}\" : \"${translation.value.plural}\").${value.map((e) => 'replaceAll("{$e}",$e)').join('.')}.replaceAll('{count}',count.toString());",
          );
        }
      }

      translationsBuffers[key] = buffer;
    }
    translationsBuffers[key] = buffer;
  }

  await File(
    path.join(
      getRootDirectory(),
      "lib",
      "translations",
      "base_localization.dart",
    ),
  ).writeAsString(
    baseTemplate.replaceFirst(
      "//{{values}}",
      baseBuffer.toString(),
    ),
  );

  for (var entry in translationsBuffers.entries) {
    await File(
      path.join(
        getRootDirectory(),
        "lib",
        "translations",
        "${entry.key}.dart",
      ),
    ).writeAsString(
      localizationTemplate
          .replaceFirst("//import", importString)
          .replaceAll(
            "/*{{LanguageCode}}*/ ",
            entry.key.toUpperCase().replaceAll(RegExp(r'[.,=_=-]'), "_"),
          )
          .replaceFirst(
            "//{{values}}",
            entry.value.toString(),
          )
          .replaceFirst(
            "/*implements*/",
            "implements BaseLocaleSyncLocalization",
          ),
    );
  }

  await File(
    path.join(
      getRootDirectory(),
      "lib",
      "translations",
      "in_memory_localization.dart",
    ),
  ).writeAsString(
    localizationTemplate
        .replaceFirst("//import", importString)
        .replaceAll("/*{{LanguageCode}}*/ ", "In_Memory_")
        .replaceFirst(
          "/*implements*/",
          "implements BaseLocaleSyncLocalization",
        )
        .replaceFirst(
          "//{{values}}",
          inMemoryBuffer.toString(),
        )
        .replaceFirst(
          "const In_Memory_LocaleSyncLocalization();",
          "const In_Memory_LocaleSyncLocalization({required this.map, required this.language,});\nfinal Map<String,dynamic> map;\nfinal String language;\n",
        ),
  );

  final exportFileBuffer = StringBuffer();
  for (var code in localizationCodes) {
    exportFileBuffer.writeln("export './$code.dart';");
  }
  exportFileBuffer.writeln("export './in_memory_localization.dart';");
  exportFileBuffer.writeln("export './base_localization.dart';");
  await File(
    path.join(
      getRootDirectory(),
      "lib",
      "translations",
      "translations.dart",
    ),
  ).writeAsString(exportFileBuffer.toString());

  final libClassBuffer = StringBuffer();

  libClassBuffer.writeln(
    "switch (locale.toString().toLowerCase().replaceFirst('_', '-')) {",
  );

  for (var code in localizationCodes) {
    libClassBuffer.writeln(
      "case '$code':",
    );
    libClassBuffer.writeln(
      "  return const ${code.toUpperCase().replaceAll(RegExp(r'[.,=_=-]'), "_")}LocaleSyncLocalization();",
    );
  }

  libClassBuffer.writeln("default:");
  libClassBuffer.writeln(
    " return const ${localizationCodes[0].toUpperCase().replaceAll(RegExp(r'[.,=_=-]'), "_")}LocaleSyncLocalization();",
  );
  libClassBuffer.writeln(
    "}",
  );

  await File(
    path.join(
      getRootDirectory(),
      "lib",
      "translations",
      "locale_sync.dart",
    ),
  ).writeAsString(
    baseClassTemplate
        .replaceFirst(
          "return const In_Memory_LocaleSyncLocalization(map: {}, language: '');",
          "",
        )
        .replaceFirst(
          "/*fallbackHandler*/",
          libClassBuffer.toString(),
        )
        .replaceFirst(
          "import 'translations/translations.dart';",
          "import 'translations.dart';",
        ),
  );
  print("Formatting generated files".blue());
  final shell = Shell();
  await shell.run("dart format lib/translations");
}