Files
kai b2af866cf0 Add bilingual UI and improve event actions layout
Add persistent German/English switching, translated UI messages and English 12-hour times. Align desktop event actions while preserving mobile layouts and record bilingual project guidance.

Include pending diary deletion exclusions. Validate both languages with nine tests.
2026-09-14 15:31:56 +02:00

47 lines
1.5 KiB
Python

"""Request-local UI translations. User content and stored identifiers stay unchanged."""
import json
from contextvars import ContextVar
from pathlib import Path
from urllib.parse import urlencode, urlsplit
LANGUAGE_COOKIE = "metalcircle_language"
current_language = ContextVar("current_language", default="de")
current_page = ContextVar("current_page", default="/")
ENGLISH = json.loads((Path(__file__).parent / "locales" / "en.json").read_text())
def gettext(message):
if not isinstance(message, str):
return message
return ENGLISH.get(message, message) if current_language.get() == "en" else message
def format_time(value):
"""Format display times without changing stored or form-submitted values."""
if current_language.get() == "en":
period = "AM" if value.hour < 12 else "PM"
return f"{value.hour % 12 or 12}:{value.minute:02d} {period}"
return value.strftime("%H:%M")
def format_datetime(value):
return f"{value.strftime('%d.%m.%Y')} {format_time(value)}"
def safe_return_path(value):
"""Only allow local absolute paths, including their query string and fragment."""
if not value or not value.startswith("/") or value.startswith("//"):
return "/"
if "\\" in value or any(ord(char) < 32 or ord(char) == 127 for char in value):
return "/"
parsed = urlsplit(value)
if parsed.scheme or parsed.netloc or parsed.path.startswith("/language/"):
return "/"
return value
def language_url(language):
return f"/language/{language}?{urlencode({'next': current_page.get()})}"