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");
}