refactorFiles function
Refactor code to use localization keys with meaningful key names.
Automatically refactors Dart/Flutter source code to replace hardcoded strings with localization calls using generated meaningful keys. This function supports both dry-run mode for preview and actual code modification.
Parameters:
extractedStrings- Map of file paths to lists of extracted stringsdryRun- If true, only shows what would be changed without modifying filesuseAppLocalizations- Whether to use AppLocalizations or Intl.messagepackageName- Package name for import statementspreserveOriginalImports- Whether to keep existing import statementspreserveConst- Whether to preserve const keywords where possible
Returns a Map of generated keys to their corresponding string values.
Example:
final keys = refactorFiles(
extractedStrings,
dryRun: false,
useAppLocalizations: true,
packageName: 'my_app'
);
Implementation
Map<String, String> refactorFiles(
Map<String, List<String>> extractedStrings, {
bool dryRun = false,
bool useAppLocalizations = true,
String packageName = 'app',
bool preserveOriginalImports = true,
bool preserveConst = false,
String? arbFilePath,
String keyFormat = 'camelCase',
}) {
var arbData = <String, String>{};
// Try to load existing ARB keys first to reuse them
Map<String, String> existingArbKeys = {};
if (arbFilePath != null && arbFilePath.isNotEmpty) {
existingArbKeys = ArbLoader.loadArbKeys(arbFilePath);
print('đ Loaded ${existingArbKeys.length} existing keys from ARB file');
}
// First, generate meaningful keys from strings
// If a string already exists in ARB, use that key
for (var entry in extractedStrings.entries) {
for (var string in entry.value) {
// Check if this string already has a key in the ARB file
String? existingKey = existingArbKeys[string];
String key;
if (existingKey != null) {
key = existingKey;
print('đ Reusing existing ARB key "$existingKey" for: $string');
} else {
// Create a meaningful key based on the content
key = KeyGenerator.generateKey(string, keyFormat: keyFormat);
// Make sure key is unique by adding number if needed
int suffix = 1;
String baseKey = key;
while (
arbData.containsKey(key) || existingArbKeys.values.contains(key)) {
key = '${baseKey}_$suffix';
suffix++;
}
}
// Store in ARB data map
arbData[key] = string;
}
}
// Now refactor each file with the consistent keys
for (var entry in extractedStrings.entries) {
var filePath = entry.key;
var file = File(filePath);
try {
print('Processing ${file.path}...');
var content = file.readAsStringSync();
var originalContent = content;
var fileChanged = false;
// Create a map of all replacements for batch processing
var replacements = <String, String>{};
for (var string in entry.value) {
// Find the key that was assigned to this string
var key = arbData.entries.firstWhere((e) => e.value == string).key;
replacements[string] = key;
}
// Apply all refactorings at once for better efficiency
final result = LocalizationRefactorer.batchRefactor(
content: content,
replacements: replacements,
useAppLocalizations: useAppLocalizations,
preserveConst: preserveConst,
);
content = result['content'];
// Track if any change was made
if (result['changed'] == true) {
fileChanged = true;
}
// Inject BuildContext parameter into Widget functions if needed
if (fileChanged && !dryRun) {
content = ContextInjector.injectContextParameter(content);
}
// Auto-fix common issues
if (fileChanged && !dryRun) {
content = AnalyzerValidator.autoFixCommonIssues(content);
}
// Only add import if file was changed and using AppLocalizations
if (fileChanged && useAppLocalizations && !dryRun) {
content =
LocalizationRefactorer.addLocalizationImport(content, packageName);
}
if (dryRun) {
if (fileChanged) {
print('--- DRY RUN: ${file.path} ---');
print('Changes would be made to this file.');
}
} else if (fileChanged && content != originalContent) {
file.writeAsStringSync(content);
print('â
Updated file: ${file.path}');
} else {
print('âšī¸ No changes needed in: ${file.path}');
}
} catch (e) {
print('â Error processing ${file.path}: $e');
}
}
// Return the ARB data for potential use
return arbData;
}