33import xml .etree .ElementTree as ET
44import sys
55import argparse
6- import html
76from pathlib import Path
8- from colorama import Fore , Style , init
7+ from colorama import Fore , Style
8+ from generate_shared import clean_string , load_glossary_dict
99
1010# Customizable mapping for output folder hierarchy
1111# Add entries here to customize the output path for specific locales
3737TRANSLATIONS_OUTPUT_DIRECTORY = args .translations_output_directory
3838NON_TRANSLATABLE_STRINGS_OUTPUT_PATH = args .non_translatable_strings_output_path
3939
40+ clean_string_extra_dict = {'{count}' : '#' }
41+
4042def parse_xliff (file_path ):
4143 tree = ET .parse (file_path )
4244 root = tree .getroot ()
@@ -69,26 +71,20 @@ def parse_xliff(file_path):
6971
7072 return translations
7173
72- def clean_string (text ):
73- # Note: any changes done for all platforms needs most likely to be done on crowdin side.
74- # So we don't want to replace -> with → for instance, we want the crowdin strings to not have those at all.
75- text = html .unescape (text ) # Unescape any HTML escaping
76- return text .strip () # Strip whitespace
7774
78- def generate_icu_pattern (target ):
75+ def generate_icu_pattern (target , glossary_dict ):
7976 if isinstance (target , dict ): # It's a plural group
8077 pattern_parts = []
8178 for form , value in target .items ():
8279 if form in ['zero' , 'one' , 'two' , 'few' , 'many' , 'other' , 'exact' , 'fractional' ]:
83- # Replace {count} with #
84- value = clean_string (value .replace ('{count}' , '#' ))
80+ value = clean_string (value , False , glossary_dict , clean_string_extra_dict )
8581 pattern_parts .append (f"{ form } [{ value } ]" )
8682
8783 return "{{count, plural, {0}}}" .format (" " .join (pattern_parts ))
8884 else : # It's a regular string
89- return clean_string (target )
85+ return clean_string (target , False , glossary_dict , clean_string_extra_dict )
9086
91- def convert_xliff_to_json (input_file , output_dir , locale , locale_two_letter_code ):
87+ def convert_xliff_to_json (input_file , output_dir , locale , locale_two_letter_code , glossary_dict ):
9288 if not os .path .exists (input_file ):
9389 raise FileNotFoundError (f"Could not find '{ input_file } ' in raw translations directory" )
9490
@@ -97,8 +93,9 @@ def convert_xliff_to_json(input_file, output_dir, locale, locale_two_letter_code
9793 sorted_translations = sorted (translations .items ())
9894 converted_translations = {}
9995
96+
10097 for resname , target in sorted_translations :
101- converted_translations [resname ] = generate_icu_pattern (target )
98+ converted_translations [resname ] = generate_icu_pattern (target , glossary_dict )
10299
103100 # Generate output files
104101 output_locale = LOCALE_PATH_MAPPING .get (locale , LOCALE_PATH_MAPPING .get (locale_two_letter_code , locale_two_letter_code ))
@@ -112,16 +109,10 @@ def convert_xliff_to_json(input_file, output_dir, locale, locale_two_letter_code
112109 file .write ('\n ' )
113110 return output_locale
114111
115- def convert_non_translatable_strings_to_type_script (input_file , output_path , exported_locales , rtl_languages ):
116- if not os .path .exists (input_file ):
117- raise FileNotFoundError (f"Could not find '{ input_file } ' in raw translations directory" )
118112
119- # Process the non-translatable string input
120- non_translatable_strings_data = {}
121- with open (input_file , 'r' , encoding = "utf-8" ) as file :
122- non_translatable_strings_data = json .load (file )
123113
124- entries = non_translatable_strings_data ['data' ]
114+ def convert_non_translatable_strings_to_type_script (input_file , output_path , exported_locales , rtl_languages ):
115+ glossary_dict = load_glossary_dict (input_file )
125116 rtl_locales = sorted ([lang ["twoLettersCode" ] for lang in rtl_languages ])
126117
127118 # Output the file in the desired format
@@ -132,9 +123,8 @@ def convert_non_translatable_strings_to_type_script(input_file, output_path, exp
132123
133124 with open (output_path , 'w' , encoding = 'utf-8' ) as file :
134125 file .write ('export enum LOCALE_DEFAULTS {\n ' )
135- for entry in entries :
136- key = entry ['data' ]['note' ]
137- text = entry ['data' ]['text' ]
126+ for key in glossary_dict :
127+ text = glossary_dict [key ]
138128 file .write (f" { key } = '{ text } ',\n " )
139129
140130 file .write ('}\n ' )
@@ -143,7 +133,7 @@ def convert_non_translatable_strings_to_type_script(input_file, output_path, exp
143133 file .write ('\n ' )
144134 file .write (f"export const crowdinLocales = [{ joined_exported_locales } ,\n ] as const;\n " )
145135 file .write ('\n ' )
146- file .write (f "export type CrowdinLocale = (typeof crowdinLocales)[number];\n " )
136+ file .write ("export type CrowdinLocale = (typeof crowdinLocales)[number];\n " )
147137 file .write ('\n ' )
148138
149139
@@ -158,6 +148,8 @@ def convert_all_files(input_directory):
158148 with open (project_info_file , 'r' , encoding = "utf-8" ) as file :
159149 project_details = json .load (file )
160150
151+ non_translatable_strings_file = os .path .join (input_directory , "_non_translatable_strings.json" )
152+
161153 # Extract the language info and sort the target languages alphabetically by locale
162154 source_language = project_details ['data' ]['sourceLanguage' ]
163155 target_languages = project_details ['data' ]['targetLanguages' ]
@@ -168,18 +160,20 @@ def convert_all_files(input_directory):
168160 # Convert the XLIFF data to the desired format
169161 print (f"\033 [2K{ Fore .WHITE } ⏳ Converting translations to target format...{ Style .RESET_ALL } " , end = '\r ' )
170162 exported_locales = []
163+ glossary_dict = load_glossary_dict (non_translatable_strings_file )
164+
171165 for language in [source_language ] + target_languages :
172166 lang_locale = language ['locale' ]
173167 lang_two_letter_code = language ['twoLettersCode' ]
174168 print (f"\033 [2K{ Fore .WHITE } ⏳ Converting translations for { lang_locale } to target format...{ Style .RESET_ALL } " , end = '\r ' )
175169 input_file = os .path .join (input_directory , f"{ lang_locale } .xliff" )
176- exported_as = convert_xliff_to_json (input_file , TRANSLATIONS_OUTPUT_DIRECTORY , lang_locale , lang_two_letter_code )
170+ exported_as = convert_xliff_to_json (input_file , TRANSLATIONS_OUTPUT_DIRECTORY , lang_locale , lang_two_letter_code , glossary_dict )
177171 exported_locales .append (exported_as )
178172 print (f"\033 [2K{ Fore .GREEN } ✅ All conversions complete{ Style .RESET_ALL } " )
179173
180174 # Convert the non-translatable strings to the desired format
181175 print (f"\033 [2K{ Fore .WHITE } ⏳ Generating static strings file...{ Style .RESET_ALL } " , end = '\r ' )
182- non_translatable_strings_file = os . path . join ( input_directory , "_non_translatable_strings.json" )
176+
183177 rtl_languages = [lang for lang in target_languages if lang ["textDirection" ] == "rtl" ]
184178 convert_non_translatable_strings_to_type_script (non_translatable_strings_file , NON_TRANSLATABLE_STRINGS_OUTPUT_PATH , exported_locales , rtl_languages )
185179 print (f"\033 [2K{ Fore .GREEN } ✅ Static string generation complete{ Style .RESET_ALL } " )
0 commit comments