Skip to content

Commit

Permalink
core: more language scripts
Browse files Browse the repository at this point in the history
1. tr_unused: find unused keys
2. tr_refine: unifies all language files to follow en_US.json
3. tr (update): now accepts multiple keys to add/remove
  • Loading branch information
MSOB7YY committed Nov 24, 2023
1 parent f4e732a commit d3a6c6f
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 17 deletions.
53 changes: 36 additions & 17 deletions tr.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,45 @@ import 'dart:io';
/// * Notes:
/// - Key is not case sensitive, ex: `my_key`, `MY_KEY` & `My_key` are all valid.
/// - Key words should be separated with underscore.
/// * NEW:
/// - now supports multiple insertions, deletions.
/// - only: `KEY` format is approved, ex: `KEY1,KEY2,KEY3`.
/// - separated by commas (,)
/// - if `KEY1,KEY2 VALUE` was used, only first key will be inserted
void main(List<String> argumentsPre) async {
final args = List<String>.from(argumentsPre);
final shouldRemove = args.remove('-r');
final argKey = args[0].toUpperCase();
final argKeyhh = args[0].toUpperCase();
final argKeys = argKeyhh.split(',');

// should remove
if (shouldRemove) {
await _removeKey(argKey);
await _removeKeys(argKeys);
return;
}

// `KEY VALUE`
if (args.length == 2) {
// should add `KEY: value` normally
final value = args[1];
await _addKey(argKey, value);
await _addKey({argKeys.first: value});
} else
// want to add `KEY` with identical value
// ex: `MY_NAME` : `My name`
if (args.length == 1) {
final valuePre = argKey.replaceAll('_', ' ').toLowerCase();
final value = "${valuePre[0].toUpperCase()}${valuePre.substring(1)}";
await _addKey(argKey, value);
final map = <String, String>{};
for (final argKey in argKeys) {
final valuePre = argKey.replaceAll('_', ' ').toLowerCase();
final value = "${valuePre[0].toUpperCase()}${valuePre.substring(1)}";
map[argKey] = value;
}
await _addKey(map);
} else {
print('Error(Missing Arguments): Supported arguments: `KEY VALUE` | `KEY` | `-r KEY`');
print('Error(Missing Arguments): Supported arguments: `KEY VALUE` | `KEY` | `KEY1,KEY2` |`-r KEY`');
}
}

Future<bool> _addKey(String argKey, String argValue) async {
Future<bool> _addKey(Map<String, String> argKeysVals) async {
try {
// -- Keys File
final file = File(_keysFilePath);
Expand All @@ -58,7 +68,9 @@ Future<bool> _addKey(String argKey, String argValue) async {
// keys.add(withoutSC.join());
// }
}
keys.insertWithOrder(argKey);
for (final argKey in argKeysVals.keys) {
keys.insertWithOrder(argKey);
}
await file.writeAsString("""
// ignore_for_file: non_constant_identifier_names
// AUTO GENERATED FILE
Expand Down Expand Up @@ -91,28 +103,33 @@ ${keys.map((e) => " String get $e => _getKey('$e');").join('\n')}
if (fileSystem.path.endsWith('.json')) {
final str = await fileSystem.readAsString();
final map = await jsonDecode(str) as Map<String, dynamic>;
map.addAll({argKey: argValue});
map.addAll(argKeysVals);
final sorted = Map<String, dynamic>.fromEntries(map.entries.toList()..sort((a, b) => a.key.compareTo(b.key)));
await fileSystem.writeAsString(encoder.convert(sorted));
}
}
}
print('Added Successfully');
print('Added ${argKeysVals.length} ${argKeysVals.length > 1 ? 'keys' : 'key'} Successfully');
return true;
} on Exception catch (e) {
print('Error Adding: $e\nRemoving Key...');
_removeKey(argKey);
print('Error Adding: $e\nRemoving Keys...');
_removeKeys(argKeysVals.keys);
return false;
}
}

Future<bool> _removeKey(String keyToRemove) async {
Future<bool> _removeKeys(Iterable<String> keysToRemove) async {
try {
// -- Keys File
final file = File(_keysFilePath);
final lines = await file.readAsLines();
final indToRemove = lines.indexWhere((element) => element.contains("String get $keyToRemove => _getKey('$keyToRemove');"));
lines.removeAt(indToRemove);
// -- reverse looping for index-related issues
for (int i = lines.length - 1; i >= 0; i--) {
final line = lines[i];
if (keysToRemove.any((keyToRemove) => line.contains("String get $keyToRemove => _getKey('$keyToRemove');"))) {
lines.removeAt(i);
}
}
await file.writeAsString('${lines.join('\n')}\n');

// -- Controller file
Expand All @@ -134,7 +151,9 @@ Future<bool> _removeKey(String keyToRemove) async {
if (fileSystem.path.endsWith('.json')) {
final str = await fileSystem.readAsString();
final map = await jsonDecode(str) as Map<String, dynamic>;
map.remove(keyToRemove);
for (final keyToRemove in keysToRemove) {
map.remove(keyToRemove);
}
await fileSystem.writeAsString(encoder.convert(map));
}
}
Expand Down
52 changes: 52 additions & 0 deletions tr_refine.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// ignore_for_file: avoid_print, depend_on_referenced_packages

import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as p;

void main(List<String> args) async {
Future<Map<String, dynamic>?> parseJSONFile(File file) async {
try {
final str = await file.readAsString();
final langMap = await jsonDecode(str) as Map<String, dynamic>;
return langMap;
} catch (e) {
print('Error parsing the map $e');
}
return null;
}

const engJsonFileName = 'en_US.json';
final mainMap = <String, dynamic>{};
final mainFile = File("$_languagesDirectoryPath\\$engJsonFileName");
final mainParsed = await parseJSONFile(mainFile);
if (mainParsed == null || mainParsed.isEmpty) {
print('Error parsing the main map, aborting...');
return;
}
mainMap.addAll(mainParsed);

const encoder = JsonEncoder.withIndent(' ');
await for (final fileSystem in Directory(_languagesDirectoryPath).list()) {
if (fileSystem is File) {
if (p.basename(fileSystem.path) != engJsonFileName && fileSystem.path.endsWith('.json')) {
final copyMap = Map<String, String>.from(mainMap);
final langMap = await parseJSONFile(fileSystem);
if (langMap == null || langMap.isEmpty) {
print('Error parsing the json of $fileSystem, skipping...');
continue;
}
for (final e in langMap.keys) {
if (copyMap[e] != null) {
// -- only assign if the key exists in the main map
// -- remaining keys (ones exists in main but not in lang) will have the same value of default map.
copyMap[e] = langMap[e];
}
}
await fileSystem.writeAsString(encoder.convert(copyMap));
}
}
}
}

const _languagesDirectoryPath = 'assets\\language\\translations';
38 changes: 38 additions & 0 deletions tr_unused.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// ignore_for_file: avoid_print

import 'dart:io';

void main(List<String> args) async {
final filesPathsAndText = <String, String>{};
await for (final d in Directory('lib').list(recursive: true)) {
if (d is File && d.path != _keysFilePath) {
filesPathsAndText[d.path] = await File(d.path).readAsString();
}
}

bool findMatchInProject(String value) {
for (final f in filesPathsAndText.keys) {
final string = filesPathsAndText[f] ?? '';
if (string.contains(value)) return true;
}
return false;
}

final file = File(_keysFilePath);
final lines = await file.readAsLines();

final notUsedKeys = <String>[];
for (final line in lines) {
final regexRes = RegExp(r'(?<=String get )(.*)(?= =>)');
final match = regexRes.firstMatch(line)?[0];
if (match != null) {
final hasMatch = findMatchInProject(match);
if (!hasMatch) notUsedKeys.add(match);
}
}
print("${notUsedKeys.length} not used keys were found");
print("--------------------------------");
print(notUsedKeys.toString());
}

const _keysFilePath = 'lib\\core\\translations\\keys.dart';

0 comments on commit d3a6c6f

Please sign in to comment.