1
1
#!/bin/python3
2
2
import re
3
- from typing import List , Tuple
4
3
5
4
OUTPUT_FILE = "./ts/localization/locales.ts"
6
5
7
6
7
+ # Define the mapping of special fields to their types and corresponding "WithX"
8
+ with_map = {
9
+ ("name" , "string" ): "WithName" ,
10
+ ("group_name" , "string" ): "WithGroupName" ,
11
+ ("community_name" , "string" ): "WithCommunityName" ,
12
+ ("other_name" , "string" ): "WithOtherName" ,
13
+ ("author" , "string" ): "WithAuthor" ,
14
+ ("emoji" , "string" ): "WithEmoji" ,
15
+ ("emoji_name" , "string" ): "WithEmojiName" ,
16
+ ("admin_name" , "string" ): "WithAdminName" ,
17
+ ("time" , "string" ): "WithTime" ,
18
+ ("time_large" , "string" ): "WithTimeLarge" ,
19
+ ("time_small" , "string" ): "WithTimeSmall" ,
20
+ ("disappearing_messages_type" , "string" ): "WithDisappearingMessagesType" ,
21
+ ("conversation_name" , "string" ): "WithConversationName" ,
22
+ ("file_type" , "string" ): "WithFileType" ,
23
+ ("date" , "string" ): "WithDate" ,
24
+ ("date_time" , "string" ): "WithDateTime" ,
25
+ ("message_snippet" , "string" ): "WithMessageSnippet" ,
26
+ ("query" , "string" ): "WithQuery" ,
27
+ ("version" , "string" ): "WithVersion" ,
28
+ ("information" , "string" ): "WithInformation" ,
29
+ ("device" , "string" ): "WithDevice" ,
30
+ ("percent_loader" , "string" ): "WithPercentLoader" ,
31
+ ("message_count" , "string" ): "WithMessageCount" ,
32
+ ("conversation_count" , "string" ): "WithConversationCount" ,
33
+ ("found_count" , "number" ): "WithFoundCount" ,
34
+ ("hash" , "string" ): "WithHash" ,
35
+ ("url" , "string" ): "WithUrl" ,
36
+ ("account_id" , "string" ): "WithAccountId" ,
37
+ ("count" , "number" ): "WithCount" ,
38
+ ("service_node_id" , "string" ): "WithServiceNodeId" ,
39
+ ("limit" , "string" ): "WithLimit" ,
40
+ ("relative_time" , "string" ): "WithRelativeTime" ,
41
+ ("icon" , "string" ): "WithIcon" ,
42
+ ("storevariant" , "string" ): "WithStoreVariant" ,
43
+ ("min" , "string" ): "WithMin" ,
44
+ ("max" , "string" ): "WithMax" ,
45
+ }
46
+
47
+
8
48
def wrapValue (value ):
9
49
"""
10
50
Wraps the given value in single quotes if it contains any characters other than letters, digits, or underscores.
@@ -62,14 +102,26 @@ def extract_vars(text):
62
102
return vars
63
103
64
104
105
+
106
+ def vars_to_record_ts (vars ):
107
+ arr = []
108
+ for var in vars :
109
+ to_append = [var , 'number' if var == 'count' or var == 'found_count' else 'string' ]
110
+ if to_append not in arr :
111
+ arr .append (to_append )
112
+
113
+ return arr
114
+
115
+
116
+
117
+
65
118
def vars_to_record (vars ):
66
119
arr = []
67
120
for var in vars :
68
121
to_append = '' + var + ': ' + ('"number"' if var == 'count' or var == 'found_count' else '"string"' )
69
122
if to_append not in arr :
70
123
arr .append (to_append )
71
124
72
- # print(arr)
73
125
if not arr :
74
126
return ''
75
127
return "{" + ', ' .join (arr ) + "}"
@@ -90,10 +142,15 @@ def generate_type_object(locales):
90
142
Returns:
91
143
str: A string representation of the JavaScript object.
92
144
"""
93
- js_object = "{\n "
94
- js_plural_object_container = "{\n "
145
+ js_object_no_args = "{\n "
146
+ js_object_with_args = "{\n "
147
+ js_plural_object_container_with_args = "{\n "
95
148
plural_pattern = r"(zero|one|two|few|many|other)\s*\[([^\]]+)\]"
96
149
150
+ tokens_simple_no_args = []
151
+ tokens_simple_with_args = {}
152
+ tokens_plurals_with_args = {}
153
+
97
154
for key , value_en in locales ['en' ].items ():
98
155
if value_en .startswith ("{count, plural, " ):
99
156
extracted_vars_en = extract_vars (value_en )
@@ -119,7 +176,6 @@ def generate_type_object(locales):
119
176
120
177
121
178
all_locales_strings = []
122
- as_record_type_en = vars_to_record (extracted_vars )
123
179
124
180
for token , localized_string in plurals_with_token :
125
181
if localized_string :
@@ -138,11 +194,11 @@ def generate_type_object(locales):
138
194
js_plural_object += "\n },"
139
195
140
196
all_locales_plurals .append (js_plural_object )
141
- js_plural_object_container += f' { wrapValue (key )} : {{\n { "\n " .join (all_locales_plurals )} \n args: { args_to_type (as_record_type_en )} \n }},\n '
197
+ js_plural_object_container_with_args += f' { wrapValue (key )} : {{\n { "\n " .join (all_locales_plurals )} \n }},\n '
198
+ tokens_plurals_with_args [key ] = vars_to_record_ts (extracted_vars )
142
199
143
200
else :
144
201
extracted_vars_en = extract_vars (value_en )
145
- as_record_type_en = vars_to_record (extracted_vars_en )
146
202
other_locales_replaced_values = [[locale , data .get (key , "" )] for locale , data in locales .items ()]
147
203
148
204
all_locales_strings = []
@@ -152,12 +208,28 @@ def generate_type_object(locales):
152
208
else :
153
209
all_locales_strings .append (f'{ wrapValue (locale .replace ("_" ,"-" ))} : "{ escape_str (value_en )} "' )
154
210
155
- # print('key',key, " other_locales_replaced_values:", other_locales_replaced_values)
156
- js_object += f' { wrapValue (key )} : {{\n { ",\n " .join (all_locales_strings )} ,\n args: { args_to_type (as_record_type_en )} \n }},\n '
211
+ if extracted_vars_en :
212
+ js_object_with_args += f' { wrapValue (key )} : {{\n { ",\n " .join (all_locales_strings )} ,\n }},\n '
213
+ tokens_simple_with_args [key ] = vars_to_record_ts (extracted_vars_en )
214
+ else :
215
+ js_object_no_args += f' { wrapValue (key )} : {{\n { ",\n " .join (all_locales_strings )} ,\n }},\n '
216
+ tokens_simple_no_args .append (key )
157
217
158
- js_object += "}"
159
- js_plural_object_container += "}"
160
- return js_object ,js_plural_object_container
218
+ tokens_simple_no_args_str = "\n '" + "' |\n '" .join (tokens_simple_no_args ) + "'"
219
+
220
+ js_object_no_args += "}"
221
+ js_object_with_args += "}"
222
+ js_plural_object_container_with_args += "}"
223
+
224
+ dicts = {
225
+ "simple_no_args" : js_object_no_args ,
226
+ "simple_with_args" : js_object_with_args ,
227
+ "plurals_with_args" : js_plural_object_container_with_args ,
228
+ "tokens_simple_no_args_str" : tokens_simple_no_args_str ,
229
+ "tokens_simple_with_args" : tokens_simple_with_args ,
230
+ "tokens_plural_with_args" : tokens_plurals_with_args ,
231
+ }
232
+ return dicts
161
233
162
234
163
235
DISCLAIMER = """
@@ -190,6 +262,40 @@ def generateLocalesType(locale, data):
190
262
return f"Locales generated at: { OUTPUT_FILE } "
191
263
192
264
265
+ def format_tokens_with_named_args (token_args_dict ):
266
+ result = []
267
+
268
+ for token , args in token_args_dict .items ():
269
+ extras = []
270
+ with_types = []
271
+
272
+ for arg_name , arg_type in args :
273
+ key = (arg_name , arg_type )
274
+ if key in with_map :
275
+ with_types .append (with_map [key ])
276
+ else :
277
+ extras .append (f"{ arg_name } : { arg_type } " )
278
+
279
+ # Join parts
280
+ joined = " & " .join (with_types )
281
+ if extras :
282
+ extras_str = "{ " + ", " .join (extras ) + " }"
283
+ joined = f"{ joined } & { extras_str } " if joined else extras_str
284
+
285
+ result .append (f" { token } : { joined } " )
286
+
287
+ return "{\n " + ",\n " .join (result ) + "\n }"
288
+
289
+
290
+ def generate_with_types (with_map ):
291
+ lines = []
292
+ for (arg_name , arg_type ), type_name in with_map .items ():
293
+ lines .append (f"type { type_name } = {{{ arg_name } : { arg_type } }};" )
294
+ return "\n " .join (lines )
295
+
296
+
297
+
298
+
193
299
def generateLocalesMergedType (locales ):
194
300
"""
195
301
Generate the locales type and write it to a file.
@@ -204,17 +310,45 @@ def generateLocalesMergedType(locales):
204
310
f"{ DISCLAIMER } "
205
311
)
206
312
313
+ ts_file .write ("import type { CrowdinLocale } from './constants';\n " )
314
+
207
315
dicts = generate_type_object (locales )
208
316
209
- dictVar = "simpleDictionary"
210
- pluralDictVar = "pluralsDictionary"
317
+ tokens_simple_with_args = dicts ['tokens_simple_with_args' ]
318
+ tokens_plural_with_args = dicts ['tokens_plural_with_args' ]
319
+
320
+ tokens_union_simple_args = format_tokens_with_named_args (tokens_simple_with_args )
321
+ tokens_union_plural_args = format_tokens_with_named_args (tokens_plural_with_args )
211
322
212
323
213
324
ts_file .write (f"""
214
- export const { dictVar } = { dicts [0 ]} as const;
325
+ { generate_with_types (with_map )}
326
+
327
+ export type TokenSimpleNoArgs = { dicts ['tokens_simple_no_args_str' ]} ;
328
+
329
+ export type TokensSimpleAndArgs = { tokens_union_simple_args } ;
330
+
331
+ export type TokensPluralAndArgs = { tokens_union_plural_args } ;
332
+
333
+ export type TokenSimpleWithArgs = { "\n '" + "' |\n '" .join (list (tokens_simple_with_args .keys ())) + "'" }
334
+
335
+ export type TokenPluralWithArgs = { "\n '" + "' |\n '" .join (list (tokens_plural_with_args .keys ())) + "'" }
336
+
337
+ export const simpleDictionaryNoArgs: Record<
338
+ TokenSimpleNoArgs,
339
+ Record<CrowdinLocale, string>
340
+ > = { dicts ['simple_no_args' ]} as const;
341
+
342
+
343
+ export const simpleDictionaryWithArgs: Record<
344
+ TokenSimpleWithArgs,
345
+ Record<CrowdinLocale, string>
346
+ > = { dicts ['simple_with_args' ]} as const;
347
+
348
+ export const pluralsDictionaryWithArgs = { dicts ['plurals_with_args' ]} as const;
215
349
216
- export const { pluralDictVar } = { dicts [1 ]} as const;
217
350
""" )
218
351
352
+
219
353
return f"Locales generated at: { OUTPUT_FILE } "
220
354
0 commit comments