From e225d58015586af1389f7f48fff13fd16b34b06f Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 25 Sep 2024 11:00:50 +1000 Subject: [PATCH] fix: build locale types fully --- tools/localization/generateLocales.py | 4 +- tools/localization/localeTypes.py | 128 +++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/tools/localization/generateLocales.py b/tools/localization/generateLocales.py index 2cbded9a5..182af90b3 100755 --- a/tools/localization/generateLocales.py +++ b/tools/localization/generateLocales.py @@ -17,7 +17,7 @@ from dynamicVariables import ( prettyPrintIssuesTable, identifyAndPrintOldDynamicVariables, extractFormattingTags, ) -from localization.localeTypes import generateLocalesType +from localization.localeTypes import generateLocalesType, generateLocalesMergedType from util.logger import console from util.fileUtils import createMappedJsonFileDictionary, writeFile @@ -116,7 +116,7 @@ if args.en_only: # Generate the locales type and write it to a file if GENERATE_TYPES: - generateTypesOutputMessage = generateLocalesType(locales["en"]) + generateTypesOutputMessage = generateLocalesMergedType(locales) console.info(generateTypesOutputMessage) localeVariables = dict() diff --git a/tools/localization/localeTypes.py b/tools/localization/localeTypes.py index 3213f39e9..05103d0b5 100644 --- a/tools/localization/localeTypes.py +++ b/tools/localization/localeTypes.py @@ -1,5 +1,6 @@ #!/bin/python3 import re +from typing import List, Tuple OUTPUT_FILE = "./ts/localization/locales.ts" @@ -49,6 +50,100 @@ def generate_js_object(data): return js_object +def extract_vars(text): + # Use a regular expression to find all strings inside curly braces + vars = re.findall(r'\{(.*?)\}', text) + return vars + +def extract_plurals(text: str) -> List[Tuple[str, str]]: + pattern = r'(\b\w+\b)\s*(\[[^\]]+\])' + + matches = re.findall(pattern, text) + + return matches + + +def vars_to_record(vars): + arr = [] + for var in vars: + to_append = '"' + var + '": ' + ('number' if var == 'count' else 'string') + if to_append not in arr: + arr.append(to_append) + + # print(arr) + if not arr: + return '' + return "{" + ', '.join(arr) + "}" + + +def replace_static_strings(str): + + # todo make those come from the glossary + replaced = str.replace("{app_name}", "Session")\ + .replace("{session_download_url}", "https://getsession.org/download")\ + .replace("{session_download_url}", "GIF")\ + .replace("{oxen_foundation}", "Oxen Foundation")\ + .replace("\"", "\\\"") + return replaced + + + + +def generate_type_object(locales): + """ + Generate a JavaScript type from a dictionary. + + Args: + data (dict): The dictionary containing key-value pairs. + + Returns: + str: A string representation of the JavaScript object. + """ + js_object = "{\n" + + for key, value_en in locales['en'].items(): + # print('value',value) + if value_en.startswith("{count, plural, "): + continue + # plurals = extract_plurals(value) + # print(plurals) + # js_plural_object = "{\n" + + # for plural in plurals: + # plural_token = plural[0] + # plural_str = plural[1].replace('#', '{count}') + # extracted_vars = extract_vars(replace_static_strings(plural_str)) + # if('count' not in extracted_vars): + # extracted_vars.append('count') + # print('extracted_vars',extracted_vars) + + # as_record_type = vars_to_record(extracted_vars) + # js_plural_object += f" {wrapValue(plural_token)}: {as_record_type},\n" + # js_plural_object += " }" + # js_object += f" {wrapValue(key)}: {js_plural_object},\n" + else: + replaced_en = replace_static_strings(value_en) + extracted_vars = extract_vars(replaced_en) + as_record_type = vars_to_record(extracted_vars) + other_locales_replaced_values = [[locale, replace_static_strings(data.get(key, ""))] for locale, data in locales.items()] + + filtered_values = [] + # filter out strings that matches the english one (i.e. untranslated strings) + for locale, replaced_val in other_locales_replaced_values: + if replaced_val == replaced_en and not locale == 'en': + # print(f"{locale}: ${key} saved content is the same as english saved.") + filtered_values.append(f"{locale}: undefined") + else: + filtered_values.append(f"{locale}: \"{replaced_val}\"") + + + # print('key',key, " other_locales_replaced_values:", other_locales_replaced_values) + js_object += f" {wrapValue(key)}:{{\n {",\n ".join(filtered_values)},\n args: {as_record_type if as_record_type else 'undefined'}\n }},\n" + + js_object += "}" + return js_object + + DISCLAIMER = """ // This file was generated by a script. Do not modify this file manually. // To make changes, modify the corresponding JSON file and re-run the script. @@ -56,7 +151,7 @@ DISCLAIMER = """ """ -def generateLocalesType(locale): +def generateLocalesType(locale, data): """ Generate the locales type and write it to a file. @@ -67,6 +162,35 @@ def generateLocalesType(locale): with open(OUTPUT_FILE, "w", encoding='utf-8') as ts_file: ts_file.write( f"{DISCLAIMER}" - f"export const en = {generate_js_object(locale)} as const;\nexport type Dictionary = typeof en;" ) + ts_file.write( + f"export const {locale} = {generate_js_object(data)} as const;\n" + ) + ts_file.write( + f"\nexport type Dictionary = typeof en;\n" + ) + + return f"Locales generated at: {OUTPUT_FILE}" + + +def generateLocalesMergedType(locales): + """ + Generate the locales type and write it to a file. + + Args: + locale: The locale dictionary containing the localization data. + """ + + # write the locale_dict to a file + with open(OUTPUT_FILE, "w", encoding='utf-8') as ts_file: + ts_file.write( + f"{DISCLAIMER}" + ) + + ts_file.write( + f"export const plop = {generate_type_object(locales)};\n" + ) + + return f"Locales generated at: {OUTPUT_FILE}" +