dev
dart 162 lines 4.56 KB
Raw
1 import 'dart:io';
2 import 'dart:convert';
3 import './print_verbose_dummy.dart';
4
5 import 'localization/localization_constants.dart';
6 import 'utils/utils.dart';
7
8 const inputPath = 'res/values/';
9 const outputPath = 'lib/generated/';
10 const localizationFileName = 'i18n.dart';
11 const localeListFileName = 'locales.dart';
12 const srcDir = 'srcDir';
13 const defaultLocale = 'en';
14
15 Future<void> main(List<String> args) async {
16 final extraInfo = args.isNotEmpty
17 ? args.fold(<String, dynamic>{}, (Map<String, dynamic> acc, String arg) {
18 final parts = arg.split('=');
19 var key = normalizeKeyName(parts[0]);
20 if (key.contains('--')) {
21 key = key.substring(2);
22 }
23 acc[key] = parts.length > 1
24 ? parts[1].isNotEmpty
25 ? parts[1]
26 : inputPath
27 : inputPath;
28 return acc;
29 })
30 : <String, dynamic>{srcDir: inputPath};
31
32 final outputDir = Directory(outputPath);
33
34 if (!outputDir.existsSync()) {
35 await outputDir.create();
36 }
37
38 extraInfo.forEach((key, dynamic value) async {
39 if (key != srcDir) {
40 print('Wrong key: $key');
41 return;
42 }
43
44 final dirPath = value as String;
45 final dir = Directory(dirPath);
46
47 if (!await dir.exists()) {
48 print('Wrong directory path: $dirPath');
49 return;
50 }
51
52 final localePath = <String, dynamic>{};
53 await dir.list(recursive: false).forEach((element) {
54 // Parse the locale from the file name (e.g. strings_pt_br.arb -> pt_BR),
55 // normalizing the case so keys match LanguageService.supportedLocales.
56 final fileName = element.uri.pathSegments.last;
57 if (!fileName.startsWith('strings_') || !fileName.endsWith('.arb')) {
58 print('Wrong file: ${element.path}');
59 return;
60 }
61 final parts =
62 fileName.substring('strings_'.length, fileName.length - '.arb'.length).split('_');
63 final locale = parts.length > 1
64 ? '${parts.first.toLowerCase()}_${parts.sublist(1).join('_').toUpperCase()}'
65 : parts.first.toLowerCase();
66 localePath[locale] = element.path;
67 });
68
69 if (!localePath.keys.contains(defaultLocale)) {
70 print("Locale list doesn't contain $defaultLocale");
71 return;
72 }
73
74 try {
75 var output = '';
76 var locales = 'const locales = [';
77
78 output += part1;
79 output += textDirectionDeclaration;
80
81 var inputContent = File(localePath[defaultLocale].toString()).readAsStringSync();
82 var config = json.decode(inputContent) as Map<String, dynamic>;
83
84 output += localizedStrings(config: config, hasOverride: false);
85 output += '}' + '\n\n';
86
87 localePath.forEach((key, dynamic value) {
88 inputContent = File(localePath[key].toString()).readAsStringSync();
89 config = json.decode(inputContent) as Map<String, dynamic>;
90
91 locales += "'$key', ";
92
93 output += 'class \$$key extends S {' + '\n';
94 output += ' const \$$key();' + '\n';
95
96 if (key != defaultLocale) {
97 output += textDirectionDeclaration;
98 output += localizedStrings(config: config, hasOverride: true);
99 }
100
101 output += '}' + '\n\n';
102 });
103
104 output += classDeclaration;
105
106 localePath.keys.forEach((key) {
107 output += ' Locale("$key", ""),' + '\n';
108 });
109
110 output += part2;
111
112 localePath.keys.forEach((key) {
113 output += ' case "$key":' + '\n';
114 output += ' S.current = const \$$key();' + '\n';
115 output += ' return SynchronousFuture<S>(S.current);' + '\n';
116 });
117
118 output += part3;
119
120 await File(outputPath + localizationFileName).writeAsString(output);
121
122 locales += '];';
123
124 await File(outputPath + localeListFileName).writeAsString(locales);
125 } catch (e) {
126 print(e.toString());
127 }
128 });
129 }
130
131 String localizedStrings({required Map<String, dynamic> config, required bool hasOverride}) {
132 var output = '';
133
134 final pattern = RegExp('[\$]{(.*?)}');
135
136 config.forEach((key, dynamic value) {
137 final matches = pattern.allMatches(value as String);
138
139 if (hasOverride) {
140 output += ' @override' + '\n';
141 }
142
143 if (matches.isEmpty) {
144 output += ' String get ${key} => \"\"\"${value}\"\"\";' + '\n';
145 } else {
146 final set = matches.map((elem) => elem.group(1)).toSet().toList();
147
148 output += ' String ${key}(';
149
150 for (var elem in set) {
151 if (elem == set.last) {
152 output += 'String ${elem}';
153 } else {
154 output += 'String ${elem}, ';
155 }
156 }
157 output += ') => \"\"\"${value}\"\"\";' + '\n';
158 }
159 });
160
161 return output;
162 }