isort's lines_after_imports = 2 conflicted with black, so run-cleanup reverted black's changes. Use isort's black profile instead and apply the resulting formatting. Also fix the flake8 errors in check_email_mixin and drop a leftover debug print. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
77 lines
2.3 KiB
Python
77 lines
2.3 KiB
Python
import json
|
|
import os
|
|
import re
|
|
|
|
ACCEPT_LANGUAGE_HEADER_REGEX = re.compile(r"([a-zA-Z]{2,3})(-[a-zA-Z\-]+)?")
|
|
|
|
|
|
def t(*args, **kwargs):
|
|
return TranslationHandler.translate(*args, **kwargs)
|
|
|
|
|
|
class TranslationHandler:
|
|
translations = {}
|
|
language = "en"
|
|
language_available = {"en": True}
|
|
always_reload_translations = False
|
|
|
|
@classmethod
|
|
def init(cls, app):
|
|
cls.app = app
|
|
cls.always_reload_translations = app.debug
|
|
app.context_processor(lambda: dict(t=t))
|
|
|
|
@classmethod
|
|
def is_language_available(cls, language):
|
|
if language not in cls.language_available:
|
|
cls.language_available[language] = os.path.exists(
|
|
cls.get_language_filepath(language)
|
|
)
|
|
return cls.language_available[language]
|
|
|
|
@classmethod
|
|
def set_language(cls, language):
|
|
if not cls.is_language_available(language):
|
|
cls.app.logger.info(f"Cannot find language {language}. Default to en.")
|
|
language = "en"
|
|
|
|
cls.language = language
|
|
if language != "en" and (
|
|
cls.always_reload_translations or language not in cls.translations
|
|
):
|
|
cls.translations[language] = json.load(
|
|
open(cls.get_language_filepath(language), "r")
|
|
)
|
|
|
|
@classmethod
|
|
def translate(cls, string, **interpolation):
|
|
if cls.language == "en":
|
|
return string.format(**interpolation)
|
|
|
|
if string not in cls.translations[cls.language]:
|
|
cls.app.logger.warning(
|
|
f'Unknown translation to {cls.language} for "{string}"'
|
|
)
|
|
return string.format(**interpolation)
|
|
|
|
return cls.translations[cls.language][string].format(**interpolation)
|
|
|
|
@classmethod
|
|
def parse_language_header(cls, header):
|
|
if not header:
|
|
return None
|
|
|
|
if "*" in header:
|
|
return None
|
|
|
|
languages = [match[0] for match in ACCEPT_LANGUAGE_HEADER_REGEX.findall(header)]
|
|
# take the first matching one
|
|
for language in languages:
|
|
if cls.is_language_available(language):
|
|
return language
|
|
return None
|
|
|
|
@classmethod
|
|
def get_language_filepath(cls, language):
|
|
return os.path.join(cls.app.root_path, f"private_static/i18n/{language}.json")
|