2024-03-14 21:49:21 +08:00
|
|
|
import 'dart:convert';
|
|
|
|
import 'dart:io';
|
|
|
|
import 'package:analyzer/dart/analysis/utilities.dart';
|
|
|
|
import 'package:analyzer/dart/analysis/features.dart';
|
|
|
|
import 'package:analyzer/dart/ast/visitor.dart';
|
|
|
|
import 'package:analyzer/dart/ast/ast.dart';
|
|
|
|
import 'package:uuid/v4.dart';
|
|
|
|
|
|
|
|
final stringResult = <String>[];
|
|
|
|
|
|
|
|
class AutoL10nTools {
|
|
|
|
void genL10nFiles() {
|
|
|
|
final dir = Directory('lib/ui');
|
|
|
|
for (var entity in dir.listSync(recursive: true)) {
|
|
|
|
if (entity is File && entity.path.endsWith('.dart')) {
|
|
|
|
print('Processing ${entity.path}...');
|
|
|
|
_processDartFile(entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (stringResult.isNotEmpty) {
|
|
|
|
final outputMap = <String, String>{};
|
|
|
|
for (var value in stringResult) {
|
|
|
|
if (outputMap.containsValue(value)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
final key = UuidV4().generate();
|
|
|
|
outputMap[key] = value;
|
|
|
|
}
|
|
|
|
// output to json
|
|
|
|
final j = json.encode(outputMap);
|
2024-03-14 23:22:56 +08:00
|
|
|
File("./lib/generated/l10n_temp.json").writeAsStringSync(j);
|
2024-03-14 21:49:21 +08:00
|
|
|
print(
|
|
|
|
"output to json file (length: ${outputMap.length}): ./lib/generated/l10n_temp.json");
|
|
|
|
}
|
2024-03-14 23:22:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void replaceL10nFiles() {
|
|
|
|
final l10nFile = File("./lib/l10n/intl_zh_CN.arb");
|
|
|
|
// readToJsonMap
|
|
|
|
final jsonMap = json.decode(l10nFile.readAsStringSync());
|
|
|
|
// read all dart File
|
|
|
|
final dir = Directory('lib/ui');
|
|
|
|
for (var entity in dir.listSync(recursive: true)) {
|
2024-03-15 00:01:06 +08:00
|
|
|
if (entity is File &&
|
|
|
|
entity.path.endsWith('.dart') &&
|
|
|
|
!(entity.path.endsWith(".g.dart") &&
|
|
|
|
entity.path.endsWith(".freezed.dart"))) {
|
2024-03-14 23:22:56 +08:00
|
|
|
print('Processing ${entity.path}...');
|
2024-03-15 00:01:06 +08:00
|
|
|
// sort map with value length
|
|
|
|
final newMap = Map.fromEntries(
|
|
|
|
jsonMap.entries.toList()
|
|
|
|
..sort((a, b) => (b.value as String).length.compareTo((a.value as String).length)),
|
|
|
|
);
|
|
|
|
_replaceDartFile(entity, newMap);
|
2024-03-14 23:22:56 +08:00
|
|
|
}
|
|
|
|
}
|
2024-03-14 21:49:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void _processDartFile(File file) {
|
|
|
|
final parseResult = parseFile(
|
|
|
|
path: file.path, featureSet: FeatureSet.latestLanguageVersion());
|
|
|
|
final unit = parseResult.unit;
|
|
|
|
unit.accept(MyAstVisitor());
|
|
|
|
}
|
2024-03-14 23:22:56 +08:00
|
|
|
|
|
|
|
void _replaceDartFile(File entity, jsonMap) {
|
2024-03-15 00:01:06 +08:00
|
|
|
for (var key in jsonMap.keys) {
|
|
|
|
if (key == "@@locale") continue;
|
|
|
|
final mapValue = jsonMap[key] as String;
|
|
|
|
if (mapValue.contains("{{") && mapValue.contains("}}")) {
|
|
|
|
print("skipping args value === $mapValue");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// 使用 CheckContainsVisitor.visitStringLiteral 获取是否有匹配的值 ,返回 true false
|
|
|
|
final parseResult = parseFile(
|
|
|
|
path: entity.path, featureSet: FeatureSet.latestLanguageVersion());
|
|
|
|
final unit = parseResult.unit;
|
|
|
|
final visitor = CheckContainsVisitor(mapValue);
|
|
|
|
unit.accept(visitor);
|
|
|
|
if (visitor.hasValue) {
|
|
|
|
// replaceDartFile with line
|
|
|
|
final lines = entity.readAsLinesSync();
|
|
|
|
final newLines = <String>[];
|
|
|
|
for (var line in lines) {
|
|
|
|
if (line.contains(mapValue) && !line.contains("\$")) {
|
|
|
|
line = line.replaceAll(mapValue, "\${S.current.$key}");
|
|
|
|
}
|
|
|
|
newLines.add(line);
|
|
|
|
}
|
|
|
|
entity.writeAsStringSync(newLines.join("\n"));
|
|
|
|
}
|
|
|
|
}
|
2024-03-14 23:22:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-15 00:01:06 +08:00
|
|
|
class CheckContainsVisitor extends GeneralizingAstVisitor {
|
|
|
|
final String mapValue;
|
2024-03-14 23:22:56 +08:00
|
|
|
|
2024-03-15 00:01:06 +08:00
|
|
|
CheckContainsVisitor(this.mapValue);
|
|
|
|
|
|
|
|
bool hasValue = false;
|
2024-03-14 23:22:56 +08:00
|
|
|
|
|
|
|
@override
|
2024-03-15 00:01:06 +08:00
|
|
|
visitStringLiteral(StringLiteral node) {
|
|
|
|
final value = node.stringValue ?? "";
|
|
|
|
if (value == mapValue) {
|
|
|
|
print('Found->visitStringLiteral: $value');
|
|
|
|
hasValue = true;
|
2024-03-14 23:22:56 +08:00
|
|
|
}
|
2024-03-15 00:01:06 +08:00
|
|
|
return super.visitStringLiteral(node);
|
2024-03-14 23:22:56 +08:00
|
|
|
}
|
2024-03-14 21:49:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
class MyAstVisitor extends GeneralizingAstVisitor {
|
|
|
|
@override
|
|
|
|
visitStringLiteral(StringLiteral node) {
|
|
|
|
final value = node.stringValue ?? "";
|
|
|
|
if (containsChinese(value)) {
|
|
|
|
print('Found->visitStringLiteral: $value');
|
|
|
|
addStringResult(value);
|
|
|
|
}
|
|
|
|
return super.visitStringLiteral(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
visitAdjacentStrings(AdjacentStrings node) {
|
|
|
|
int interpolationIndex = 0;
|
|
|
|
var result = '';
|
|
|
|
for (var string in node.strings) {
|
|
|
|
if (string is SimpleStringLiteral) {
|
|
|
|
result += string.value;
|
|
|
|
} else if (string is StringInterpolation) {
|
|
|
|
for (var element in string.elements) {
|
|
|
|
if (element is InterpolationString) {
|
|
|
|
result += element.value;
|
|
|
|
} else if (element is InterpolationExpression) {
|
2024-03-16 17:35:52 +08:00
|
|
|
result += '{v${interpolationIndex++}}';
|
2024-03-14 21:49:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (containsChinese(result)) {
|
|
|
|
print('Found->visitAdjacentStrings: $result');
|
|
|
|
addStringResult(result);
|
|
|
|
}
|
|
|
|
return super.visitAdjacentStrings(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
visitStringInterpolation(StringInterpolation node) {
|
|
|
|
int interpolationIndex = 0;
|
|
|
|
var result = '';
|
|
|
|
for (var element in node.elements) {
|
|
|
|
if (element is InterpolationString) {
|
|
|
|
result += element.value;
|
|
|
|
} else if (element is InterpolationExpression) {
|
2024-03-16 17:35:52 +08:00
|
|
|
result += '{v${interpolationIndex++}}';
|
2024-03-14 21:49:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (containsChinese(result)) {
|
|
|
|
print('Found->visitStringInterpolation: $result');
|
|
|
|
addStringResult(result);
|
|
|
|
}
|
|
|
|
return super.visitStringInterpolation(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
visitInterpolationExpression(InterpolationExpression node) {
|
|
|
|
int interpolationIndex = 0;
|
2024-03-16 17:35:52 +08:00
|
|
|
final value = '{v${interpolationIndex++}}';
|
2024-03-14 21:49:21 +08:00
|
|
|
if (containsChinese(value)) {
|
|
|
|
print('Found->visitInterpolationExpression: $value');
|
|
|
|
addStringResult(value);
|
|
|
|
}
|
|
|
|
return super.visitInterpolationExpression(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool containsChinese(String input) {
|
|
|
|
return RegExp(r'[\u4e00-\u9fa5]').hasMatch(input);
|
|
|
|
}
|
|
|
|
|
|
|
|
addStringResult(String value) {
|
|
|
|
stringResult.add(value);
|
|
|
|
}
|
|
|
|
}
|