You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/tools/localization/localeTypes.py

197 lines
5.7 KiB
Python

#!/bin/python3
import re
from typing import List, Tuple
OUTPUT_FILE = "./ts/localization/locales.ts"
def wrapValue(value):
"""
Wraps the given value in single quotes if it contains any characters other than letters, digits, or underscores.
Args:
value (str): The value to be wrapped.
Returns:
str: The wrapped value if it contains any special characters, otherwise the original value.
"""
if re.search(r"[^a-zA-Z0-9_]", value):
return f"'{value}'"
return value
def parseValue(value):
"""
Parses the given value by replacing single quotes with escaped single quotes.
Args:
value (str): The value to be parsed.
Returns:
str: The parsed value with escaped single quotes.
"""
return value.replace("'", "\\'")
def generate_js_object(data):
"""
Generate a JavaScript object 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 in data.items():
js_object += f" {wrapValue(key)}: '{parseValue(value)}',\n"
js_object += "}"
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.
"""
def generateLocalesType(locale, data):
"""
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 {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}"