From 6b46751fe30144d31cfb9ac603fd42f0317ea55b Mon Sep 17 00:00:00 2001 From: Mandel Olaiya Date: Sat, 2 May 2026 21:20:13 +0200 Subject: [PATCH] fix: language switcher uses translated page URLs --- .../headers/partials/carbasa-user-bar.html | 23 ++++--- .../templatetags/localized_navigation.py | 67 ++++++++++++++++++- 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/mandelstudio/templates/oxyan/headers/partials/carbasa-user-bar.html b/mandelstudio/templates/oxyan/headers/partials/carbasa-user-bar.html index c070b2c..c6a9b72 100644 --- a/mandelstudio/templates/oxyan/headers/partials/carbasa-user-bar.html +++ b/mandelstudio/templates/oxyan/headers/partials/carbasa-user-bar.html @@ -1,9 +1,10 @@ -{% load i18n %} +{% load i18n localized_navigation %}
{% get_current_language as current_language %} {% get_available_languages as available_languages %} {% get_language_info_list for available_languages as languages %} + {% request_language_options as language_options %} diff --git a/mandelstudio/templatetags/localized_navigation.py b/mandelstudio/templatetags/localized_navigation.py index 017aaa7..2af5d7d 100644 --- a/mandelstudio/templatetags/localized_navigation.py +++ b/mandelstudio/templatetags/localized_navigation.py @@ -3,7 +3,7 @@ from __future__ import annotations from django import template from django.conf import settings -from wagtail.models import Page +from wagtail.models import Locale, Page, Site register = template.Library() @@ -47,6 +47,63 @@ def _build_absolute_url(request, path: str | None, page=None) -> str: return path or "" +def _resolve_page_from_request(request) -> Page | None: + """ + Best-effort resolution of the Wagtail page for the current request. + + This is used by the language switcher ESI fragment where `page/self` isn't + available in the template context. + """ + if request is None: + return None + + try: + site = Site.find_for_request(request) + except Exception: # pragma: no cover + site = None + + if site is None: + site = Site.objects.filter(is_default_site=True).first() + if site is None: + return None + + path = getattr(request, "path_info", None) or getattr(request, "path", "/") + path_components = [c for c in path.strip("/").split("/") if c] + + try: + locale_codes = set(Locale.objects.values_list("language_code", flat=True)) + except Exception: # pragma: no cover + locale_codes = set() + + if path_components and path_components[0] in locale_codes: + path_components = path_components[1:] + + root = site.root_page + language_code = getattr(request, "LANGUAGE_CODE", None) + locale = None + if language_code: + try: + locale = Locale.objects.get( + language_code=_normalize_language_code(language_code) + ) + except Locale.DoesNotExist: + locale = None + + if locale is not None: + translated_root = ( + Page.objects.filter(translation_key=root.translation_key, locale=locale) + .specific() + .first() + ) + if translated_root is not None: + root = translated_root + + try: + return root.specific.route(request, path_components).page.specific + except Exception: + return None + + @register.simple_tag def page_language_options(page): labels = { @@ -82,6 +139,14 @@ def page_language_options(page): return options +@register.simple_tag(takes_context=True) +def request_language_options(context): + page = context.get("page") or context.get("self") + if page is None: + page = _resolve_page_from_request(context.get("request")) + return page_language_options(page) + + @register.simple_tag(takes_context=True) def page_canonical_url(context): request = context.get("request")