多语言

This commit is contained in:
czz
2025-07-30 16:48:48 +08:00
parent 92b6896176
commit 300e3b31f6
96 changed files with 3741 additions and 2710 deletions

View File

@@ -1,232 +1,120 @@
// import 'dart:io';
// void main(List<String> 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<void> 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<List<int>> getCommentRanges(String content) {
// final ranges = <List<int>>[];
// 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;
// }
import 'dart:io';
import 'dart:convert';
void main(List<String> args) async {
if (args.length < 2) {
print('Usage: dart script.dart <target_path> <json_file_path>');
return;
}
// 默认使用当前目录和同级目录下的 chinese_texts.json
final targetPath = args.isNotEmpty ? args[0] : Directory.current.path;
final jsonFilePath = args.length > 1 ? args[1] : 'chinese_texts.json';
final targetPath = args[0];
final jsonFilePath = args[1];
print('目标路径: $targetPath');
print('JSON文件: $jsonFilePath');
// 加载JSON文件
final jsonFile = File(jsonFilePath);
if (!jsonFile.existsSync()) {
print('JSON file not found: $jsonFilePath');
return;
print('错误: JSON文件不存在: $jsonFilePath');
print('请确保文件存在或提供完整路径');
exit(1);
}
final jsonContent = await jsonFile.readAsString();
final jsonMap = json.decode(jsonContent) as Map<String, dynamic>;
final targetKeys = jsonMap.keys.toSet();
// 检查目标路径类型
final type = FileSystemEntity.typeSync(targetPath);
if (type == FileSystemEntityType.notFound) {
print('Path not found: $targetPath');
return;
print('错误: 目标路径不存在: $targetPath');
exit(1);
}
int modifiedCount = 0;
int processedCount = 0;
if (type == FileSystemEntityType.file && targetPath.endsWith('.dart')) {
await processDartFile(File(targetPath), targetKeys);
// 处理单个文件
processedCount = 1;
if (await processDartFile(File(targetPath), targetKeys)) {
modifiedCount++;
}
} else if (type == FileSystemEntityType.directory) {
final directory = Directory(targetPath);
print('Scanning directory: $targetPath');
await for (final entity
in directory.list(recursive: true, followLinks: false)) {
// 处理目录
print('开始扫描Dart文件...');
await for (final entity in Directory(targetPath).list(recursive: true)) {
if (entity is File && entity.path.endsWith('.dart')) {
await processDartFile(entity, targetKeys);
processedCount++;
if (await processDartFile(entity, targetKeys)) {
modifiedCount++;
}
}
}
print('Processing completed');
} else {
print('Unsupported path type: $targetPath');
print('错误: 不支持的路径类型: $targetPath');
exit(1);
}
print('\n处理结果:');
print('扫描文件: $processedCount');
print('修改文件: $modifiedCount');
print('未修改文件: ${processedCount - modifiedCount}');
}
Future<void> processDartFile(File file, Set<String> targetKeys) async {
final content = await file.readAsString();
final commentRanges = getCommentRanges(content);
final regex = RegExp(r'''(['"])([^'"]*?[\u4e00-\u9fa5][^'"]*?)\1''');
Future<bool> processDartFile(File file, Set<String> targetKeys) async {
try {
final content = await file.readAsString();
final commentRanges = getCommentRanges(content);
final regex = RegExp(r'''(['"])((?:\\.|[^\\])*?)\1''');
final matches = regex.allMatches(content).toList();
if (matches.isEmpty) {
print('✓ No matches in: ${file.path}');
return;
}
final buffer = StringBuffer();
int lastIndex = 0;
bool hasChanges = false;
final sb = StringBuffer();
int lastIndex = 0;
bool hasChanges = false;
for (final match in regex.allMatches(content)) {
final start = match.start;
final end = match.end;
final text = match.group(2)!;
for (final match in matches) {
final start = match.start;
final end = match.end;
// 跳过注释
if (commentRanges.any((r) => start >= r[0] && start < r[1])) {
buffer.write(content.substring(lastIndex, end));
lastIndex = end;
continue;
}
// 跳过注释中的内容
if (commentRanges.any((range) => start >= range[0] && start < range[1])) {
sb.write(content.substring(lastIndex, end));
lastIndex = end;
continue;
}
final fullMatch = match.group(0)!;
final textContent = match.group(2)!;
// 检查是否在目标keys中
if (targetKeys.contains(textContent)) {
// 检查是否已经包含.tr
if (!isAlreadyTrCall(content, start, end)) {
sb.write(content.substring(lastIndex, start));
sb.write('$fullMatch.tr');
// 检查是否是需要国际化的字符串
if (targetKeys.contains(text) && !isAlreadyTrCall(content, end)) {
buffer.write(content.substring(lastIndex, end));
buffer.write('.tr');
lastIndex = end;
hasChanges = true;
lastIndex = end;
} else {
sb.write(content.substring(lastIndex, end));
lastIndex = end;
}
} else {
sb.write(content.substring(lastIndex, end));
lastIndex = end;
}
}
sb.write(content.substring(lastIndex));
if (hasChanges) {
await file.writeAsString(sb.toString());
print('✓ Modified: ${file.path}');
} else {
print('✓ No changes needed: ${file.path}');
if (hasChanges) {
buffer.write(content.substring(lastIndex));
await file.writeAsString(buffer.toString());
print('已修改: ${file.path}');
return true;
}
return false;
} catch (e) {
print('处理 ${file.path} 出错: $e');
return false;
}
}
bool isAlreadyTrCall(String content, int start, int end) {
// 检查字符串后面是否紧跟.tr
final afterString = content.substring(end);
return RegExp(r'^\s*\.tr\b').hasMatch(afterString);
bool isAlreadyTrCall(String content, int endIndex) {
return endIndex < content.length &&
content.substring(endIndex).trim().startsWith('.tr');
}
List<List<int>> getCommentRanges(String content) {
final ranges = <List<int>>[];
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]);
}
ranges.addAll(RegExp(r'/\*.*?\*/', dotAll: true)
.allMatches(content)
.map((m) => [m.start, m.end]));
ranges.addAll(RegExp(r'//.*?$', multiLine: true)
.allMatches(content)
.map((m) => [m.start, m.end]));
return ranges;
}