|
@@ -0,0 +1,133 @@
|
|
|
|
|
+import 'package:build/build.dart';
|
|
|
|
|
+import 'package:xml/xml.dart';
|
|
|
|
|
+import 'package:glob/glob.dart';
|
|
|
|
|
+import 'package:path/path.dart' as path;
|
|
|
|
|
+import 'flutter_string_get_config.dart';
|
|
|
|
|
+
|
|
|
|
|
+Builder stringXmlWatcherBuilder(BuilderOptions options) {
|
|
|
|
|
+ return StringXmlWatcherBuilder();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+class StringXmlWatcherBuilder implements Builder {
|
|
|
|
|
+ late final FlutterStringGetConfig _config;
|
|
|
|
|
+ late final Glob _targetXmlGlob;
|
|
|
|
|
+
|
|
|
|
|
+ StringXmlWatcherBuilder() {
|
|
|
|
|
+ _config = FlutterStringGetConfig.fromProject();
|
|
|
|
|
+
|
|
|
|
|
+ print('string_get_runner inputDir ${_config.inputDir}');
|
|
|
|
|
+ print('string_get_runner outputFile ${_config.outputFile}');
|
|
|
|
|
+ print('string_get_runner language ${_config.language}');
|
|
|
|
|
+
|
|
|
|
|
+ _targetXmlGlob = Glob(_config.inputDir);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @override
|
|
|
|
|
+ Future<void> build(BuildStep buildStep) async {
|
|
|
|
|
+ print('string_get_runner build');
|
|
|
|
|
+ final xmlFiles = await buildStep.findAssets(_targetXmlGlob).toList();
|
|
|
|
|
+ final (buffer, multiBuffer) = await _processXmlFiles(buildStep, xmlFiles);
|
|
|
|
|
+
|
|
|
|
|
+ final outputId = AssetId(buildStep.inputId.package, _config.outputFile);
|
|
|
|
|
+ await buildStep.writeAsString(
|
|
|
|
|
+ outputId, buffer.toString() + multiBuffer.toString());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Future<(StringBuffer, StringBuffer)> _processXmlFiles(
|
|
|
|
|
+ BuildStep buildStep,
|
|
|
|
|
+ List<AssetId> xmlFiles,
|
|
|
|
|
+ ) async {
|
|
|
|
|
+ final buffer = StringBuffer();
|
|
|
|
|
+ final multiBuffer = StringBuffer();
|
|
|
|
|
+
|
|
|
|
|
+ buffer.writeln('import \'package:get/get.dart\';');
|
|
|
|
|
+ buffer.writeln();
|
|
|
|
|
+ buffer.writeln('class StringName {');
|
|
|
|
|
+ buffer.writeln(' StringName._();');
|
|
|
|
|
+
|
|
|
|
|
+ final Map<String, Map<String, String>> multiLangMap = {};
|
|
|
|
|
+
|
|
|
|
|
+ for (final file in xmlFiles) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ final content = await buildStep.readAsString(file);
|
|
|
|
|
+ final document = XmlDocument.parse(content);
|
|
|
|
|
+ final languageCode = _extractLanguageCode(file.path);
|
|
|
|
|
+ print('languageCode :$languageCode');
|
|
|
|
|
+
|
|
|
|
|
+ multiLangMap.putIfAbsent(languageCode, () => {});
|
|
|
|
|
+
|
|
|
|
|
+ for (final element in document.findAllElements('string')) {
|
|
|
|
|
+ final name = element.getAttribute('name');
|
|
|
|
|
+ final value = processXmlText(element.text);
|
|
|
|
|
+
|
|
|
|
|
+ if (name != null) {
|
|
|
|
|
+ multiLangMap[languageCode]![name] = value;
|
|
|
|
|
+
|
|
|
|
|
+ if (languageCode == _config.language) {
|
|
|
|
|
+ final camelCaseName = _toCamelCase(name);
|
|
|
|
|
+ buffer.writeln(
|
|
|
|
|
+ ' static String get $camelCaseName => \'$name\'.tr; // $value',
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ print('❌(string_get_runner)Error processing file ${file.path}: $e');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ buffer.writeln('}');
|
|
|
|
|
+
|
|
|
|
|
+ multiBuffer.writeln('class StringMultiSource {');
|
|
|
|
|
+ multiBuffer.writeln(' StringMultiSource._();');
|
|
|
|
|
+ multiBuffer.writeln(
|
|
|
|
|
+ ' static const Map<String, Map<String, String>> translations = {');
|
|
|
|
|
+
|
|
|
|
|
+ for (final entry in multiLangMap.entries) {
|
|
|
|
|
+ multiBuffer.writeln(' \'${entry.key}\': {');
|
|
|
|
|
+ for (final item in entry.value.entries) {
|
|
|
|
|
+ multiBuffer.writeln(' \'${item.key}\': \'${item.value}\',');
|
|
|
|
|
+ }
|
|
|
|
|
+ multiBuffer.writeln(' },');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ multiBuffer.writeln(' };');
|
|
|
|
|
+ multiBuffer.writeln('}');
|
|
|
|
|
+
|
|
|
|
|
+ print('✅ string_get_runner file generated successfully!');
|
|
|
|
|
+ return (buffer, multiBuffer);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String processXmlText(String original) {
|
|
|
|
|
+ return original
|
|
|
|
|
+ .replaceAll('\r\n', ' ')
|
|
|
|
|
+ .replaceAll('\n', ' ')
|
|
|
|
|
+ .replaceAll(RegExp(r'\s+'), ' ')
|
|
|
|
|
+ .trim()
|
|
|
|
|
+ .replaceAll("'", "\\'");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String _toCamelCase(String snakeCase) {
|
|
|
|
|
+ return snakeCase.split('_').map((word) {
|
|
|
|
|
+ if (word == snakeCase.split('_').first) return word;
|
|
|
|
|
+ return word[0].toUpperCase() + word.substring(1);
|
|
|
|
|
+ }).join('');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String _extractLanguageCode(String filePath) {
|
|
|
|
|
+ final segments = path.split(filePath);
|
|
|
|
|
+ final stringIndex = segments.indexOf('string');
|
|
|
|
|
+
|
|
|
|
|
+ if (stringIndex >= 0 && stringIndex + 1 < segments.length) {
|
|
|
|
|
+ final langDir = segments[stringIndex + 1];
|
|
|
|
|
+ return langDir == 'base' ? _config.language : langDir;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return _config.language;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @override
|
|
|
|
|
+ Map<String, List<String>> get buildExtensions => {
|
|
|
|
|
+ r'$package$': [path.normalize(_config.outputFile)],
|
|
|
|
|
+ };
|
|
|
|
|
+}
|