Skip to content

Commit

Permalink
Prevent errors on get_url_parts when a non-content-language locale is…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
gasman committed Nov 6, 2020
1 parent 37e9e1d commit f378f48
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.txt
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions docs/releases/2.11.1.rst
Expand Up @@ -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)
16 changes: 16 additions & 0 deletions wagtail/admin/tests/api/test_pages.py
Expand Up @@ -2,13 +2,15 @@
import datetime
import json

from django.contrib.auth import get_user_model
from django.urls import reverse
from django.utils import timezone

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

Expand Down Expand Up @@ -101,6 +103,20 @@ def test_private_pages_appear_in_list(self):
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
Expand Down
24 changes: 18 additions & 6 deletions wagtail/core/models.py
Expand Up @@ -1585,16 +1585,28 @@ def get_url_parts(self, request=None):
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:
Expand Down
6 changes: 6 additions & 0 deletions wagtail/core/tests/test_page_model.py
Expand Up @@ -499,6 +499,12 @@ def test_urls_with_region_specific_translation_activated_thats_in_wagtail_conten
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/')
Expand Down

0 comments on commit f378f48

Please sign in to comment.