Widget: Fix language on first iframe request

This commit is contained in:
Raphael Michel
2024-01-26 11:44:02 +01:00
parent 734b376e05
commit eac88b5ef7
5 changed files with 52 additions and 21 deletions

View File

@@ -20,7 +20,9 @@
# <https://www.gnu.org/licenses/>.
#
from rest_framework import exceptions
from rest_framework.authentication import SessionAuthentication as BaseSessionAuthentication
from rest_framework.authentication import (
SessionAuthentication as BaseSessionAuthentication,
)
from pretix.multidomain.middlewares import CsrfViewMiddleware

View File

@@ -44,6 +44,25 @@ from pretix.multidomain.urlreverse import (
_supported = None
def get_supported_language(requested_language, allowed_languages, default_language):
language = requested_language
if language not in allowed_languages:
firstpart = language.split('-')[0]
if firstpart in allowed_languages:
language = firstpart
else:
language = default_language
for lang in allowed_languages:
if lang.startswith(firstpart + '-'):
language = lang
break
if language not in allowed_languages:
# This seems redundant, but can happen in the rare edge case that settings.locale is (wrongfully)
# not part of settings.locales
language = allowed_languages[0]
return language
class LocaleMiddleware(MiddlewareMixin):
"""
@@ -65,20 +84,11 @@ class LocaleMiddleware(MiddlewareMixin):
settings_holder = None
if settings_holder:
if language not in settings_holder.settings.locales:
firstpart = language.split('-')[0]
if firstpart in settings_holder.settings.locales:
language = firstpart
else:
language = settings_holder.settings.locale
for lang in settings_holder.settings.locales:
if lang.startswith(firstpart + '-'):
language = lang
break
if language not in settings_holder.settings.locales:
# This seems redundant, but can happen in the rare edge case that settings.locale is (wrongfully)
# not part of settings.locales
language = settings_holder.settings.locales[0]
language = get_supported_language(
language,
settings_holder.settings.locales,
settings_holder.settings.locale,
)
if '-' not in language and settings_holder.settings.region:
language += '-' + settings_holder.settings.region
else:

View File

@@ -41,12 +41,14 @@ from itertools import groupby
from django.conf import settings
from django.contrib import messages
from django.db.models import Exists, OuterRef, Prefetch, Sum
from django.utils import translation
from django.utils.functional import cached_property
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from django_scopes import scopes_disabled
from pretix.base.i18n import language
from pretix.base.i18n import get_language_without_region
from pretix.base.middleware import get_supported_language
from pretix.base.models import (
CartPosition, Customer, InvoiceAddress, ItemAddOn, Question,
QuestionAnswer, QuestionOption, TaxRule,
@@ -455,11 +457,24 @@ def iframe_entry_view_wrapper(view_func):
locale = request.GET.get('locale')
if locale and locale in [lc for lc, ll in settings.LANGUAGES]:
region = None
lng = locale
if hasattr(request, 'event'):
lng = get_supported_language(
lng,
request.event.settings.locales,
request.event.settings.locale,
)
region = request.event.settings.region
with language(locale, region):
resp = view_func(request, *args, **kwargs)
if '-' not in lng and region:
lng += '-' + region.lower()
# with language() is not good enough here we really need to take the role of LocaleMiddleware and modify
# global state, because template rendering might be happening lazily.
translation.activate(lng)
request.LANGUAGE_CODE = get_language_without_region()
resp = view_func(request, *args, **kwargs)
max_age = 10 * 365 * 24 * 60 * 60
set_cookie_without_samesite(
request,

View File

@@ -24,9 +24,9 @@ import time
import pytest
from bs4 import BeautifulSoup
from django.test import Client
from tests.base import extract_form_fields
from pretix.base.models import Organizer
from tests.base import extract_form_fields
@pytest.mark.django_db

View File

@@ -58,9 +58,13 @@ class WidgetCartTest(CartTestMixin, TestCase):
)
def test_iframe_entry_view_wrapper(self):
self.client.get('/%s/%s/?iframe=1&locale=de' % (self.orga.slug, self.event.slug))
self.event.settings.locales = ["de", "en"]
r = self.client.get('/%s/%s/?iframe=1&locale=de' % (self.orga.slug, self.event.slug), headers={
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
})
assert 'iframe_session' in self.client.session
assert self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value == "de"
assert r.headers["Content-Language"] == "de"
def test_allow_frame_if_namespaced(self):
response = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug))