Prevent errors on get_url_parts when a non-content-language locale is active (#6521)

Fixes #6510 and #6511

Catch the LookupError from get_supported_content_language_variant so that if the active language is not one that is recognised as a content language, the URL prefix will be left unchanged from the page's reported locale.

Additionally, skip the `translation.override` when WAGTAIL_I18N_ENABLED is false; this accounts for the fact that existing sites may have used alternative / custom i18n implementations involving i18n_patterns, and on these sites we can't rely on the page's locale field to be meaningful. That way, we restore the pre-2.11 behaviour: if the existing i18n code was using some kind of wrapper around the get_url_parts call, then that will work again; and if not, the URL will reflect the current active locale, which is no worse than before.
pull/6541/head
Matt Westcott 2020-11-05 16:44:36 +00:00
rodzic 37e9e1d54d
commit f378f48e14
5 zmienionych plików z 42 dodań i 6 usunięć

Wyświetl plik

@ -12,6 +12,7 @@ Changelog
* Fix: Ensure that cached `wagtail_site_root_paths` structures from older Wagtail versions are invalidated (Sævar Öfjörð Magnússon)
* Fix: Avoid circular import between wagtail.admin.auth and custom user models (Matt Westcott)
* Fix: Prevent error on resolving page URLs when a locale outside of `WAGTAIL_CONTENT_LANGUAGES` is active (Matt Westcott)
2.11 LTS (02.11.2020)

Wyświetl plik

@ -15,3 +15,4 @@ Bug fixes
* Ensure that cached ``wagtail_site_root_paths`` structures from older Wagtail versions are invalidated (Sævar Öfjörð Magnússon)
* Avoid circular import between wagtail.admin.auth and custom user models (Matt Westcott)
* Prevent error on resolving page URLs when a locale outside of ``WAGTAIL_CONTENT_LANGUAGES`` is active (Matt Westcott)

Wyświetl plik

@ -2,6 +2,7 @@ import collections
import datetime
import json
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.utils import timezone
@ -9,6 +10,7 @@ from wagtail.api.v2.tests.test_pages import TestPageDetail, TestPageListing
from wagtail.core.models import Locale, Page
from wagtail.tests.demosite import models
from wagtail.tests.testapp.models import SimplePage, StreamPage
from wagtail.users.models import UserProfile
from .utils import AdminAPITestCase
@ -101,6 +103,20 @@ class TestAdminPageListing(AdminAPITestCase, TestPageListing):
content = json.loads(response.content.decode('UTF-8'))
self.assertEqual(content['meta']['total_count'], new_total_count)
def test_get_in_non_content_language(self):
# set logged-in user's admin UI language to Swedish
user = get_user_model().objects.get(email='test@email.com')
UserProfile.objects.update_or_create(user=user, defaults={'preferred_language': 'se'})
response = self.get_response()
self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-type'], 'application/json')
# Will crash if the JSON is invalid
content = json.loads(response.content.decode('UTF-8'))
self.assertIn('meta', content)
# FIELDS
# Not applicable to the admin API

Wyświetl plik

@ -1585,16 +1585,28 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
else:
site_id, root_path, root_url, language_code = possible_sites[0]
# If the active language code is a variant of the page's language, then
# use that instead
# This is used when LANGUAGES contain more languages than WAGTAIL_CONTENT_LANGUAGES
if get_supported_content_language_variant(translation.get_language()) == language_code:
language_code = translation.get_language()
use_wagtail_i18n = getattr(settings, 'WAGTAIL_I18N_ENABLED', False)
if use_wagtail_i18n:
# If the active language code is a variant of the page's language, then
# use that instead
# This is used when LANGUAGES contain more languages than WAGTAIL_CONTENT_LANGUAGES
try:
if get_supported_content_language_variant(translation.get_language()) == language_code:
language_code = translation.get_language()
except LookupError:
# active language code is not a recognised content language, so leave
# page's language code unchanged
pass
# The page may not be routable because wagtail_serve is not registered
# This may be the case if Wagtail is used headless
try:
with translation.override(language_code):
if use_wagtail_i18n:
with translation.override(language_code):
page_path = reverse(
'wagtail_serve', args=(self.url_path[len(root_path):],))
else:
page_path = reverse(
'wagtail_serve', args=(self.url_path[len(root_path):],))
except NoReverseMatch:

Wyświetl plik

@ -499,6 +499,12 @@ class TestRoutingWithI18N(TestRouting):
with translation.override("en-us"):
self.test_urls()
def test_urls_with_language_not_in_wagtail_content_languages(self):
# If the active locale doesn't map to anything in WAGTAIL_CONTENT_LANGUAGES,
# URL prefixes should remain the same as the page's reported locale
with translation.override("se"):
self.test_urls()
def test_urls_with_different_language_tree(self):
default_site = Site.objects.get(is_default_site=True)
homepage = Page.objects.get(url_path='/home/')