string_xml_watcher_builder.dart 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import 'package:build/build.dart';
  2. import 'package:xml/xml.dart';
  3. import 'package:glob/glob.dart';
  4. import 'package:path/path.dart' as path;
  5. import 'flutter_string_get_config.dart';
  6. Builder stringXmlWatcherBuilder(BuilderOptions options) {
  7. return StringXmlWatcherBuilder();
  8. }
  9. class StringXmlWatcherBuilder implements Builder {
  10. late final FlutterStringGetConfig _config;
  11. late final Glob _targetXmlGlob;
  12. StringXmlWatcherBuilder() {
  13. _config = FlutterStringGetConfig.fromProject();
  14. print('string_get_runner inputDir ${_config.inputDir}');
  15. print('string_get_runner outputFile ${_config.outputFile}');
  16. print('string_get_runner language ${_config.language}');
  17. _targetXmlGlob = Glob(_config.inputDir);
  18. }
  19. @override
  20. Future<void> build(BuildStep buildStep) async {
  21. print('string_get_runner build');
  22. final xmlFiles = await buildStep.findAssets(_targetXmlGlob).toList();
  23. final (buffer, multiBuffer) = await _processXmlFiles(buildStep, xmlFiles);
  24. final outputId = AssetId(buildStep.inputId.package, _config.outputFile);
  25. await buildStep.writeAsString(
  26. outputId, buffer.toString() + multiBuffer.toString());
  27. }
  28. Future<(StringBuffer, StringBuffer)> _processXmlFiles(
  29. BuildStep buildStep,
  30. List<AssetId> xmlFiles,
  31. ) async {
  32. final buffer = StringBuffer();
  33. final multiBuffer = StringBuffer();
  34. buffer.writeln('import \'package:get/get.dart\';');
  35. buffer.writeln();
  36. buffer.writeln('class StringName {');
  37. buffer.writeln(' StringName._();');
  38. final Map<String, Map<String, String>> multiLangMap = {};
  39. for (final file in xmlFiles) {
  40. try {
  41. final content = await buildStep.readAsString(file);
  42. final document = XmlDocument.parse(content);
  43. final languageCode = _extractLanguageCode(file.path);
  44. print('languageCode :$languageCode');
  45. multiLangMap.putIfAbsent(languageCode, () => {});
  46. for (final element in document.findAllElements('string')) {
  47. final name = element.getAttribute('name');
  48. final value = processXmlText(element.text);
  49. if (name != null) {
  50. multiLangMap[languageCode]![name] = value;
  51. if (languageCode == _config.language) {
  52. final camelCaseName = _toCamelCase(name);
  53. buffer.writeln(
  54. ' static String get $camelCaseName => \'$name\'.tr; // $value',
  55. );
  56. }
  57. }
  58. }
  59. } catch (e) {
  60. print('❌(string_get_runner)Error processing file ${file.path}: $e');
  61. }
  62. }
  63. buffer.writeln('}');
  64. multiBuffer.writeln('class StringMultiSource {');
  65. multiBuffer.writeln(' StringMultiSource._();');
  66. multiBuffer.writeln(
  67. ' static const Map<String, Map<String, String>> translations = {');
  68. for (final entry in multiLangMap.entries) {
  69. multiBuffer.writeln(' \'${entry.key}\': {');
  70. for (final item in entry.value.entries) {
  71. multiBuffer.writeln(' \'${item.key}\': \'${item.value}\',');
  72. }
  73. multiBuffer.writeln(' },');
  74. }
  75. multiBuffer.writeln(' };');
  76. multiBuffer.writeln('}');
  77. print('✅ string_get_runner file generated successfully!');
  78. return (buffer, multiBuffer);
  79. }
  80. String processXmlText(String original) {
  81. return original
  82. .replaceAll('\r\n', ' ')
  83. .replaceAll('\n', ' ')
  84. .replaceAll(RegExp(r'\s+'), ' ')
  85. .trim()
  86. .replaceAll("'", "\\'");
  87. }
  88. String _toCamelCase(String snakeCase) {
  89. return snakeCase.split('_').map((word) {
  90. if (word == snakeCase.split('_').first) return word;
  91. return word[0].toUpperCase() + word.substring(1);
  92. }).join('');
  93. }
  94. String _extractLanguageCode(String filePath) {
  95. final segments = path.split(filePath);
  96. final stringIndex = segments.indexOf('string');
  97. if (stringIndex >= 0 && stringIndex + 1 < segments.length) {
  98. final langDir = segments[stringIndex + 1];
  99. return langDir == 'base' ? _config.language : langDir;
  100. }
  101. return _config.language;
  102. }
  103. @override
  104. Map<String, List<String>> get buildExtensions => {
  105. r'$package$': [path.normalize(_config.outputFile)],
  106. };
  107. }