Removed old PHP code, migrated to Python and Flask

Update .dockerignore, .env, and 503 more files...
This commit is contained in:
2024-10-20 16:20:37 +02:00
parent 169e4b4fe0
commit a930331d6c
394 changed files with 4705 additions and 190131 deletions

72
website/l10n/__init__.py Normal file
View File

@@ -0,0 +1,72 @@
import copy
from typing import Optional
from locked_dict.locked_dict import LockedDict
class Localizer:
_langs_data: LockedDict[LockedDict[str, str]]
_default_lang: str
_allowed_langs: list[str]
def __init__(self, default_lang: str, allowed_langs: Optional[list[str]]):
self._langs_data = LockedDict()
self._default_lang = default_lang
self._allowed_langs = allowed_langs
if self._allowed_langs is None:
self._allowed_langs = list()
self._allowed_langs.append(self._default_lang)
def add_lang(self, lang: str):
if lang not in self._langs_data.keys():
self._langs_data[lang] = LockedDict()
def add_domain(self, lang: str, domain: str, domain_data: Optional[dict[str, str]], strip_prefix: bool = False):
if domain not in self._langs_data[lang].keys():
self._langs_data[lang][domain] = LockedDict()
if strip_prefix:
new_domain_data = dict()
for key, value in domain_data.items():
if key.startswith(f"{domain}."):
new_domain_data[key[len(f"{domain}."):]] = value
domain_data = new_domain_data
self._langs_data[lang][domain].update(domain_data)
def _localize_internal(self, lang: str, domain: str, key: str, args: list[str] = None) -> Optional[str]:
if lang not in self._allowed_langs:
return None
if lang not in self._langs_data.keys():
return None
lang_data = self._langs_data[lang]
if domain not in lang_data.keys():
return None
domain_data = lang_data[domain]
if key not in domain_data.keys():
return None
localized_text = domain_data[key]
if args is not None:
for arg_index, arg_value in enumerate(args):
localized_text = localized_text.replace(f"%{arg_index}", arg_value)
return localized_text
def localize(self, lang: str, domain: str, key: str, args: list[str] = None) -> str:
localized_string = None
if localized_string is None:
localized_string = self._localize_internal(lang, domain, key, args)
if localized_string is None and lang != self._default_lang:
localized_string = self._localize_internal(self._default_lang, domain, key, args)
if localized_string is None:
return domain + "." + key
return localized_string

168
website/l10n/utils.py Normal file
View File

@@ -0,0 +1,168 @@
import json
import os.path
from pathlib import Path
from typing import Optional
import yaml
from . import Localizer
DEFAULT_LANG = "en"
ALLOWED_LANGS = ["en", "fr"]
L10N = Localizer(DEFAULT_LANG, ALLOWED_LANGS)
def reload_strings(strings_root: str) -> None:
global L10N
for allowed_lang in ALLOWED_LANGS:
print(f"Adding lang '{allowed_lang}'...")
L10N.add_lang(allowed_lang)
for lang_dir in os.listdir(strings_root):
lang_dir_path = os.path.join(strings_root, lang_dir)
if not os.path.isdir(lang_dir_path):
print(f"Ignoring lang non-folder '{lang_dir}'...")
continue
if lang_dir not in ALLOWED_LANGS:
print(f"Ignoring lang folder '{lang_dir}'...")
continue
for lang_domain in os.listdir(os.path.join(lang_dir_path)):
if lang_domain.startswith("_"):
continue
lang_domain_path = os.path.join(os.getcwd(), strings_root, lang_dir, lang_domain)
if not os.path.isfile(lang_domain_path):
continue
domain_key = str(Path(lang_domain).with_suffix(''))
if lang_domain.endswith(".json"):
print(f"Loading JSON lang data from '{lang_domain_path}'...")
L10N.add_domain(
lang_dir,
domain_key,
json.loads(open(lang_domain_path, "rb").read().decode("utf-8"))
)
if lang_domain.endswith(".yml"):
print(f"Loading YAML lang data from '{lang_domain_path}'...")
L10N.add_domain(
lang_dir,
domain_key,
yaml.safe_load(open(lang_domain_path, "rb").read().decode("utf-8"))
)
def localize(strings_key: str, domain: str, language: str, args: list[str] = None) -> str:
global L10N
# print(f"l10n({strings_key}, {domain}, {language})")
return L10N.localize(language, domain, strings_key, args)
def get_user_lang(url_lang: Optional[str], header_langs: Optional[str], simplify_entries: bool = True) -> str:
if url_lang is not None:
return url_lang
if header_langs is None:
return DEFAULT_LANG
processed_header_langs: list[tuple[str, float]] = list()
processed_header_langs.append((DEFAULT_LANG, 0.01))
for header_lang in header_langs.split(","):
header_lang_parts: list[str] = header_lang.split(";")
# Modifying entries without a "q=<float>" part to have a '0.1' value
if len(header_lang_parts) == 1:
header_lang_parts.append("0.1")
if len(header_lang_parts) != 2:
continue
header_lang_parts: list[str, float]
# Simplifying complex entries from "en-US" to "en".
# We'll ignore duplicates since it won't matter after sorting.
if simplify_entries and "-" in header_lang_parts[0]:
header_lang_parts[0] = header_lang_parts[0].split("-")[0]
# Only allowing supported languages
if header_lang_parts[0] not in ALLOWED_LANGS:
continue
# Parsing the language's weight
try:
header_lang_parts[1] = float(header_lang_parts[1].replace("q=", ""))
except ValueError:
continue
processed_header_langs.append((header_lang_parts[0], header_lang_parts[1], ))
# Returning the preferred language
return max(processed_header_langs, key=lambda x: x[1])[0]
def l10n_url_abs(url: str, raw_lang: Optional[str] = None) -> str:
if raw_lang is None:
return f"/{url}".replace("//", "/")
else:
return f"/{raw_lang}/{url}".replace("//", "/")
def l10n_url_switch(url: str, new_lang: Optional[str] = None) -> str:
for allowed_lang in ALLOWED_LANGS:
url = url.replace(f"/{allowed_lang}/", "/")
if new_lang is not None:
url = "/" + new_lang + url
return url.replace("//", "/")
# STRINGS = dict()
# STRINGS[DEFAULT_LANG] = dict()
# STRINGS["_compile_date"] = "1970-01-01T00:00:00.000000+00:00Z"
#
#
# def reload_strings(strings_file: str) -> None:
# global STRINGS
# STRINGS = dict()
# STRINGS[DEFAULT_LANG] = dict()
# STRINGS["_compile_date"] = "1970-01-01T00:00:00.000000+00:00Z"
# STRINGS = json.loads(open(strings_file, "r").read())
#
#
# def localize_internal(string_key: str, language: str, lang_data: dict, fallback: Optional[str]) -> Optional[str]:
# if language not in ALLOWED_LANGS:
# return fallback
#
# if language not in lang_data.keys():
# language = DEFAULT_LANG
#
# localized_string = lang_data[language].get(string_key)
# if localized_string is None and language != DEFAULT_LANG:
# localized_string = lang_data[DEFAULT_LANG].get(string_key)
#
# if localized_string is None:
# return fallback
# return localized_string
#
#
# def localize(strings_key: str, language: str, extra_lang_data: Optional[dict] = None) -> str:
# localized_string = None
#
# if extra_lang_data is not None:
# localized_string = localize_internal(strings_key, language, extra_lang_data, None)
#
# if localized_string is None:
# localized_string = localize_internal(strings_key, language, STRINGS, None)
#
# if localized_string is None:
# return f"${strings_key}"
# return localized_string