From efca08e8d71cb227c374ace644c48f4cc32ae0db Mon Sep 17 00:00:00 2001 From: czz <862977248@qq.com> Date: Fri, 25 Jul 2025 16:35:35 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=AD=E8=A8=80=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tool/add_tr_to_chinese.dart | 108 ++++++++++++++++++++++++++++++++++++ tool/extract_chinese.dart | 46 +++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 tool/add_tr_to_chinese.dart create mode 100644 tool/extract_chinese.dart diff --git a/tool/add_tr_to_chinese.dart b/tool/add_tr_to_chinese.dart new file mode 100644 index 0000000..49b2c9b --- /dev/null +++ b/tool/add_tr_to_chinese.dart @@ -0,0 +1,108 @@ +import 'dart:io'; + +void main(List args) async { + final targetPath = args.isNotEmpty ? args[0] : Directory.current.path; + final type = FileSystemEntity.typeSync(targetPath); + + if (type == FileSystemEntityType.notFound) { + print('路径不存在: $targetPath'); + return; + } + + if (type == FileSystemEntityType.file && targetPath.endsWith('.dart')) { + await processDartFile(File(targetPath)); + } else if (type == FileSystemEntityType.directory) { + final directory = Directory(targetPath); + print('扫描目录: $targetPath'); + + await for (final entity + in directory.list(recursive: true, followLinks: false)) { + if (entity is File && entity.path.endsWith('.dart')) { + await processDartFile(entity); + } + } + print('处理完成'); + } else { + print('不支持的路径类型: $targetPath'); + } +} + +Future processDartFile(File file) async { + final content = await file.readAsString(); + + // 获取注释范围 + final commentRanges = getCommentRanges(content); + + // 匹配带中文的引号字符串(单/双引号) + final regex = RegExp(r'''(['"])([^'"]*?[\u4e00-\u9fa5][^'"]*?)\1'''); + + final matches = regex.allMatches(content).toList(); + if (matches.isEmpty) return; + + final sb = StringBuffer(); + int lastIndex = 0; + + for (final match in matches) { + final start = match.start; + final end = match.end; + + // 跳过注释中的内容 + if (commentRanges.any((range) => start >= range[0] && start < range[1])) { + continue; + } + + // 插入上次结束到当前匹配之间的代码 + sb.write(content.substring(lastIndex, start)); + + final fullMatch = match.group(0)!; + + // 判断是否已处于 .tr 表达式中 + if (isAlreadyTrCall(content, start, end)) { + sb.write(fullMatch); // 不修改 + } else { + sb.write('$fullMatch.tr'); // 添加 .tr + } + + lastIndex = end; + } + + sb.write(content.substring(lastIndex)); + + final result = sb.toString(); + if (result != content) { + await file.writeAsString(result); + print('✅ 修改完成: ${file.path}'); + } else { + print('✔ 无需修改: ${file.path}'); + } +} + +/// 判断该字符串是否已是 .tr 调用的一部分 +bool isAlreadyTrCall(String content, int start, int end) { + final after = content.substring(end); + final before = content.substring(0, start); + + // 检查匹配后是否直接跟 .tr (允许空格) + final hasTrAfter = RegExp(r'^\s*\.tr\b').hasMatch(after); + + // 检查匹配前是否已经出现 .tr (形如 .tr'xxx' 也考虑在内) + final hasTrBefore = RegExp(r'\.tr\s*$').hasMatch(before); + + return hasTrAfter || hasTrBefore; +} + +/// 找出所有注释区间 (start, end) +List> getCommentRanges(String content) { + final ranges = >[]; + + final multiLine = RegExp(r'/\*[\s\S]*?\*/'); + final singleLine = RegExp(r'//.*'); + + for (final m in multiLine.allMatches(content)) { + ranges.add([m.start, m.end]); + } + for (final m in singleLine.allMatches(content)) { + ranges.add([m.start, m.end]); + } + return ranges; +} diff --git a/tool/extract_chinese.dart b/tool/extract_chinese.dart new file mode 100644 index 0000000..3dc0987 --- /dev/null +++ b/tool/extract_chinese.dart @@ -0,0 +1,46 @@ +import 'dart:io'; +import 'dart:convert'; + +void main(List args) async { + final dirPath = args.isNotEmpty ? args[0] : Directory.current.path; + + print('扫描目录: $dirPath'); + + final directory = Directory(dirPath); + if (!directory.existsSync()) { + print('目录不存在'); + return; + } + + final dartFiles = []; + await for (var entity + in directory.list(recursive: true, followLinks: false)) { + if (entity is File && entity.path.endsWith('.dart')) { + dartFiles.add(entity); + } + } + + final chineseReg = RegExp(r'[\u4e00-\u9fa5]+'); + final chineseSet = {}; + + for (var file in dartFiles) { + final content = await file.readAsString(); + final uncommented = removeComments(content); + final matches = chineseReg.allMatches(uncommented); + chineseSet.addAll(matches.map((m) => m.group(0)!)); + } + + final resultMap = {for (var text in chineseSet) text: text}; + final jsonString = const JsonEncoder.withIndent(' ').convert(resultMap); + + final outputFile = File('chinese_texts.json'); + await outputFile.writeAsString(jsonString); + + print('中文文本已保存到: ${outputFile.path}'); +} + +String removeComments(String source) { + source = source.replaceAll(RegExp(r'\/\*[\s\S]*?\*\/'), ''); + source = source.replaceAll(RegExp(r'\/\/.*'), ''); + return source; +}