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: 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: 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) 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) * 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) * 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 datetime
import json import json
from django.contrib.auth import get_user_model
from django.urls import reverse from django.urls import reverse
from django.utils import timezone 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.core.models import Locale, Page
from wagtail.tests.demosite import models from wagtail.tests.demosite import models
from wagtail.tests.testapp.models import SimplePage, StreamPage from wagtail.tests.testapp.models import SimplePage, StreamPage
from wagtail.users.models import UserProfile
from .utils import AdminAPITestCase from .utils import AdminAPITestCase
@ -101,6 +103,20 @@ class TestAdminPageListing(AdminAPITestCase, TestPageListing):
content = json.loads(response.content.decode('UTF-8')) content = json.loads(response.content.decode('UTF-8'))
self.assertEqual(content['meta']['total_count'], new_total_count) 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 # FIELDS
# Not applicable to the admin API # Not applicable to the admin API

Wyświetl plik

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

Wyświetl plik

@ -499,6 +499,12 @@ class TestRoutingWithI18N(TestRouting):
with translation.override("en-us"): with translation.override("en-us"):
self.test_urls() 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): def test_urls_with_different_language_tree(self):
default_site = Site.objects.get(is_default_site=True) default_site = Site.objects.get(is_default_site=True)
homepage = Page.objects.get(url_path='/home/') homepage = Page.objects.get(url_path='/home/')