25-3/18/1
This commit is contained in:
218
lib/controller/packages/lingo/lingo_hunter.dart
Normal file
218
lib/controller/packages/lingo/lingo_hunter.dart
Normal file
@@ -0,0 +1,218 @@
|
||||
import 'dart:io';
|
||||
import 'dart:convert';
|
||||
|
||||
abstract class LingoHunter {
|
||||
/// Extracts translatable strings...
|
||||
static Future<void> extractAndCreateTranslationFiles({
|
||||
required String baseLang,
|
||||
required List<String> langs,
|
||||
String? projectDirectory,
|
||||
String? outputDirectory,
|
||||
bool translateBaseLang = true,
|
||||
List<RegExp>? additionalRegExps,
|
||||
bool overrideRegExps = false,
|
||||
List<String> fileExtensions = const ['.dart'],
|
||||
}) async {
|
||||
// 1. Find project root (improved logic)
|
||||
String projectRoot;
|
||||
if (projectDirectory != null) {
|
||||
// Use provided directory, but check if it's valid
|
||||
if (!await Directory(projectDirectory).exists()) {
|
||||
throw ArgumentError(
|
||||
"The provided projectDirectory '$projectDirectory' does not exist.");
|
||||
}
|
||||
projectRoot = projectDirectory;
|
||||
} else {
|
||||
projectRoot = await _findProjectRoot(); // Use the corrected function
|
||||
}
|
||||
|
||||
// 2. Use the project root as output directory if not specified
|
||||
final String outputDir = outputDirectory ?? projectRoot;
|
||||
|
||||
// 3. Output Directory Verification (Create if necessary)
|
||||
final Directory outputDirObj = Directory(outputDir);
|
||||
if (!await outputDirObj.exists()) {
|
||||
try {
|
||||
await outputDirObj.create(recursive: true);
|
||||
} catch (e) {
|
||||
throw Exception(
|
||||
"Failed to create output directory: $outputDir. Error: $e");
|
||||
}
|
||||
}
|
||||
|
||||
print("Project root directory: $projectRoot");
|
||||
print("Output directory: $outputDir");
|
||||
|
||||
// 4. Extract translatable strings
|
||||
final Set<String> strings = await extractStringsFromFlutterProject(
|
||||
directory: projectRoot, // Use the validated projectRoot
|
||||
additionalRegExps: additionalRegExps,
|
||||
overrideRegExps: overrideRegExps,
|
||||
fileExtensions: fileExtensions,
|
||||
);
|
||||
|
||||
// 5. Generate translation files
|
||||
await _createTranslationFiles(
|
||||
strings: strings,
|
||||
outputDirectory: outputDir,
|
||||
baseLang: baseLang,
|
||||
langs: langs,
|
||||
translateBaseLang: translateBaseLang,
|
||||
);
|
||||
|
||||
print("Successfully extracted strings and generated translation files.");
|
||||
}
|
||||
|
||||
/// Finds the project's root directory (corrected)
|
||||
static Future<String> _findProjectRoot() async {
|
||||
Directory current = Directory.current;
|
||||
int maxIterations = 10; // Prevent infinite loop
|
||||
int count = 0;
|
||||
|
||||
while (count < maxIterations) {
|
||||
if (await File('${current.path}/pubspec.yaml').exists()) {
|
||||
return current.path; // Return the directory *containing* pubspec.yaml
|
||||
}
|
||||
|
||||
if (current.path == current.parent.path) {
|
||||
break; // Reached root, stop searching
|
||||
}
|
||||
|
||||
current = current.parent;
|
||||
count++;
|
||||
}
|
||||
|
||||
// If `pubspec.yaml` was not found, throw an exception
|
||||
throw Exception(
|
||||
"`pubspec.yaml` not found in the current directory or its parents.");
|
||||
}
|
||||
|
||||
/// Extracts translatable strings (no changes needed here)
|
||||
static Future<Set<String>> extractStringsFromFlutterProject({
|
||||
required String directory,
|
||||
List<RegExp>? additionalRegExps,
|
||||
bool overrideRegExps = false,
|
||||
List<String> fileExtensions = const ['.dart'],
|
||||
}) async {
|
||||
// ... (rest of the function remains the same) ...
|
||||
final List<RegExp> defaultPatterns = [
|
||||
RegExp(r'"([^"]+)"\.tr\(\)'), // "string".tr()
|
||||
RegExp(r"'([^']+)'\.tr\(\)"), // 'string'.tr()
|
||||
RegExp(r'"([^"]+)"\.tr'), // "string".tr
|
||||
RegExp(r"'([^']+)'\.tr"), // 'string'.tr
|
||||
RegExp(r'"([^"]+)"\.tr\(\w+\)'), // "string".tr(context)
|
||||
RegExp(r"'([^']+)'\.tr\(\w+\)"), // 'string'.tr(context)
|
||||
RegExp(r'context\.tr\("([^"]+)"\)'), // context.tr("string")
|
||||
RegExp(r"context\.tr\('([^']+)'\)"), // context.tr('string')
|
||||
RegExp(r'tr\(\w+, "([^"]+)"\)'), // tr(context, "string")
|
||||
RegExp(r"tr\(\w+, '([^']+)'\)"), // tr(context, 'string')
|
||||
RegExp(r'tr\("([^"]+)"\)'), // tr("string")
|
||||
RegExp(r"tr\('([^']+)'\)"), // tr('string')
|
||||
RegExp(r'"([^"]+)"\.tr\(args: \[.*?\]\)'), // "string".tr(args: [])
|
||||
RegExp(r'"([^"]+)"\.plural\(\d+\)'), // "string".plural(3)
|
||||
//Intl Package Patterns
|
||||
RegExp(r'AppLocalizations\.of\(context\)!\.translate\("([^"]+)"\)'),
|
||||
];
|
||||
|
||||
// Determine the patterns to use
|
||||
List<RegExp> patterns;
|
||||
if (overrideRegExps && additionalRegExps != null) {
|
||||
patterns = additionalRegExps;
|
||||
} else {
|
||||
patterns = [...defaultPatterns];
|
||||
if (additionalRegExps != null) {
|
||||
patterns.addAll(additionalRegExps);
|
||||
}
|
||||
}
|
||||
|
||||
final Set<String> strings = {};
|
||||
final Directory projectDirObj = Directory(directory);
|
||||
|
||||
// Check if the directory exists *before* listing
|
||||
if (!await projectDirObj.exists()) {
|
||||
throw ArgumentError("The directory '$directory' does not exist.");
|
||||
}
|
||||
|
||||
final List<FileSystemEntity> entities =
|
||||
await projectDirObj.list(recursive: true).toList();
|
||||
|
||||
// Filter files by the specified extensions
|
||||
final List<File> filteredFiles = entities
|
||||
.whereType<File>()
|
||||
.where((file) => fileExtensions.any((ext) => file.path.endsWith(ext)))
|
||||
.toList();
|
||||
|
||||
// Extract strings from files
|
||||
for (final File file in filteredFiles) {
|
||||
final String content = await file.readAsString();
|
||||
|
||||
for (final RegExp pattern in patterns) {
|
||||
final Iterable<RegExpMatch> matches = pattern.allMatches(content);
|
||||
|
||||
for (final RegExpMatch match in matches) {
|
||||
if (match.groupCount >= 1 && match.group(1) != null) {
|
||||
strings.add(match.group(1)!);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strings;
|
||||
}
|
||||
|
||||
/// Creates translation files (no changes needed)
|
||||
static Future<void> _createTranslationFiles({
|
||||
required Set<String> strings,
|
||||
required String outputDirectory,
|
||||
required String baseLang,
|
||||
required List<String> langs,
|
||||
bool translateBaseLang = true,
|
||||
}) async {
|
||||
// ... (rest of the function remains the same) ...
|
||||
final Directory outputDir = Directory(outputDirectory);
|
||||
if (!await outputDir.exists()) {
|
||||
await outputDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// Always create the base language file, even if `translateBaseLang` is false
|
||||
final String baseFilePath = '$outputDirectory/translations_$baseLang.json';
|
||||
final Map<String, String> baseStrings = {
|
||||
for (final string in strings) string: translateBaseLang ? string : ""
|
||||
};
|
||||
await _writeTranslationFile(baseFilePath, baseStrings);
|
||||
|
||||
for (final String lang in langs) {
|
||||
final String langFilePath = '$outputDirectory/translations_$lang.json';
|
||||
final Map<String, String> langStrings = {
|
||||
for (final string in strings) string: ""
|
||||
};
|
||||
await _writeTranslationFile(langFilePath, langStrings);
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes a translation file (no changes needed)
|
||||
static Future<void> _writeTranslationFile(
|
||||
String filePath, Map<String, String> strings) async {
|
||||
// ... (rest of the function remains the same) ...
|
||||
final File file = File(filePath);
|
||||
final StringBuffer content = StringBuffer();
|
||||
content.writeln('{');
|
||||
|
||||
int index = 0;
|
||||
for (final MapEntry<String, String> entry in strings.entries) {
|
||||
final String comma = (index < strings.length - 1) ? ',' : '';
|
||||
final String key =
|
||||
jsonEncode(entry.key).substring(1, jsonEncode(entry.key).length - 1);
|
||||
final String value = entry.value.isEmpty
|
||||
? ""
|
||||
: jsonEncode(entry.value)
|
||||
.substring(1, jsonEncode(entry.value).length - 1);
|
||||
|
||||
content.writeln(' "$key": "$value"$comma');
|
||||
index++;
|
||||
}
|
||||
|
||||
content.writeln('}');
|
||||
await file.writeAsString(content.toString());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user