diff --git a/padelnomics/src/padelnomics/content/routes.py b/padelnomics/src/padelnomics/content/routes.py index 1032153..98ab76e 100644 --- a/padelnomics/src/padelnomics/content/routes.py +++ b/padelnomics/src/padelnomics/content/routes.py @@ -10,6 +10,7 @@ from markupsafe import Markup from quart import Blueprint, abort, g, render_template, request from ..core import capture_waitlist_email, config, csrf_protect, fetch_all, fetch_one, waitlist_gate +from ..i18n import get_translations bp = Blueprint( "content", @@ -37,9 +38,20 @@ SECTION_TEMPLATES = { } # Standalone Jinja2 env for baking scenario cards into static HTML. -# Does not require a Quart app context. +# Does not use a Quart request context, so url_for and t are injected +# explicitly. Baked content is always EN (admin operation). _TEMPLATE_DIR = Path(__file__).parent / "templates" _bake_env = Environment(loader=FileSystemLoader(str(_TEMPLATE_DIR)), autoescape=True) +_bake_env.filters["tformat"] = lambda s, **kw: s.format_map(kw) + +# Hardcoded EN URL stubs — the bake env has no request context so Quart's +# url_for cannot be used. Only endpoints referenced by scenario card templates +# need to be listed here. +_BAKE_URLS: dict[str, str] = { + "planner.index": "/en/planner/", + "directory.index": "/en/directory/", +} +_bake_env.globals["url_for"] = lambda endpoint, **kw: _BAKE_URLS.get(endpoint, f"/{endpoint}") def is_reserved_path(url_path: str) -> bool: @@ -79,7 +91,12 @@ async def bake_scenario_cards(html: str) -> str: state_data = json.loads(scenario["state_json"]) tmpl = _bake_env.get_template(template_name) - card_html = tmpl.render(scenario=scenario, d=calc_data, s=state_data) + # Baking is always in the EN admin context; t and lang are required + # by scenario card templates for translated labels. + card_html = tmpl.render( + scenario=scenario, d=calc_data, s=state_data, + lang="en", t=get_translations("en"), + ) html = html[:match.start()] + card_html + html[match.end():] return html diff --git a/padelnomics/src/padelnomics/content/templates/article_detail.html b/padelnomics/src/padelnomics/content/templates/article_detail.html index b11cf24..7df25ad 100644 --- a/padelnomics/src/padelnomics/content/templates/article_detail.html +++ b/padelnomics/src/padelnomics/content/templates/article_detail.html @@ -40,7 +40,7 @@

{{ article.title }}

- {% if article.published_at %}{% if lang == 'de' %}Veröffentlicht{% else %}Published{% endif %} {{ article.published_at[:10] }} · {% endif %}{% if lang == 'de' %}Padelnomics Forschung{% else %}Padelnomics Research{% endif %} + {% if article.published_at %}{{ t.article_detail_published_label }} {{ article.published_at[:10] }} · {% endif %}{{ t.article_detail_research_label }}

diff --git a/padelnomics/src/padelnomics/content/templates/markets.html b/padelnomics/src/padelnomics/content/templates/markets.html index e6337ff..1acb1aa 100644 --- a/padelnomics/src/padelnomics/content/templates/markets.html +++ b/padelnomics/src/padelnomics/content/templates/markets.html @@ -1,11 +1,11 @@ {% extends "base.html" %} -{% block title %}{% if lang == 'de' %}Padel-Märkte - {{ config.APP_NAME }}{% else %}Padel Markets - {{ config.APP_NAME }}{% endif %}{% endblock %} +{% block title %}{{ t.markets_page_title }} - {{ config.APP_NAME }}{% endblock %} {% block head %} - - - + + + {% endblock %} {% block content %} @@ -19,7 +19,7 @@
- +
- +