summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergio <smaisidoro@gmail.com>2022-10-02 13:59:13 +0300
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-10-13 10:38:26 +0200
commit94e7f471c4edef845a4fe5e3160132997b4cca81 (patch)
treee470a0ca3cb2ac861b2ac62b805c042381ba3c72
parent004f985b918d5ea36fbed9b050459dd22edaf396 (diff)
Fixed #34069 -- Made LocaleMiddleware respect language from requests when i18n patterns are used.
-rw-r--r--django/middleware/locale.py33
-rw-r--r--django/utils/translation/trans_null.py2
-rw-r--r--django/utils/translation/trans_real.py6
-rw-r--r--docs/releases/4.2.txt4
-rw-r--r--tests/i18n/tests.py21
5 files changed, 43 insertions, 23 deletions
diff --git a/django/middleware/locale.py b/django/middleware/locale.py
index 71db230da2..bc1d862574 100644
--- a/django/middleware/locale.py
+++ b/django/middleware/locale.py
@@ -16,28 +16,37 @@ class LocaleMiddleware(MiddlewareMixin):
response_redirect_class = HttpResponseRedirect
+ def get_fallback_language(self, request):
+ """
+ Return the fallback language for the current request based on the
+ settings. If LANGUAGE_CODE is a variant not included in the supported
+ languages, get_fallback_language() will try to fallback to a supported
+ generic variant.
+
+ Can be overridden to have a fallback language depending on the request,
+ e.g. based on top level domain.
+ """
+ try:
+ return translation.get_supported_language_variant(settings.LANGUAGE_CODE)
+ except LookupError:
+ return settings.LANGUAGE_CODE
+
def process_request(self, request):
urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF)
- (
- i18n_patterns_used,
- prefixed_default_language,
- ) = is_language_prefix_patterns_used(urlconf)
+ i18n_patterns_used, _ = is_language_prefix_patterns_used(urlconf)
language = translation.get_language_from_request(
request, check_path=i18n_patterns_used
)
- language_from_path = translation.get_language_from_path(request.path_info)
- if (
- not language_from_path
- and i18n_patterns_used
- and not prefixed_default_language
- ):
- language = settings.LANGUAGE_CODE
+ if not language:
+ language = self.get_fallback_language(request)
+
translation.activate(language)
request.LANGUAGE_CODE = translation.get_language()
def process_response(self, request, response):
language = translation.get_language()
language_from_path = translation.get_language_from_path(request.path_info)
+ language_from_request = translation.get_language_from_request(request)
urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF)
(
i18n_patterns_used,
@@ -48,7 +57,7 @@ class LocaleMiddleware(MiddlewareMixin):
response.status_code == 404
and not language_from_path
and i18n_patterns_used
- and prefixed_default_language
+ and (prefixed_default_language or language_from_request)
):
# Maybe the language code is missing in the URL? Try adding the
# language prefix and redirecting to that URL.
diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py
index c8bfb1256e..595a705e2b 100644
--- a/django/utils/translation/trans_null.py
+++ b/django/utils/translation/trans_null.py
@@ -53,7 +53,7 @@ def check_for_language(x):
def get_language_from_request(request, check_path=False):
- return settings.LANGUAGE_CODE
+ return None
def get_language_from_path(request):
diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index 423f30eaba..595a9ec2e4 100644
--- a/django/utils/translation/trans_real.py
+++ b/django/utils/translation/trans_real.py
@@ -578,11 +578,7 @@ def get_language_from_request(request, check_path=False):
return get_supported_language_variant(accept_lang)
except LookupError:
continue
-
- try:
- return get_supported_language_variant(settings.LANGUAGE_CODE)
- except LookupError:
- return settings.LANGUAGE_CODE
+ return None
@functools.lru_cache(maxsize=1000)
diff --git a/docs/releases/4.2.txt b/docs/releases/4.2.txt
index c3ddb7c7af..6a87a5bbe9 100644
--- a/docs/releases/4.2.txt
+++ b/docs/releases/4.2.txt
@@ -186,6 +186,10 @@ Internationalization
* Added support and translations for the Central Kurdish (Sorani) language.
+* The :class:`~django.middleware.locale.LocaleMiddleware` now respects a
+ language from the request when :func:`~django.conf.urls.i18n.i18n_patterns`
+ is used with the ``prefix_default_language`` argument set to ``False``.
+
Logging
~~~~~~~
diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py
index 53585a1871..1fec6009a5 100644
--- a/tests/i18n/tests.py
+++ b/tests/i18n/tests.py
@@ -2137,8 +2137,22 @@ class UnprefixedDefaultLanguageTests(SimpleTestCase):
response = self.client.get("/fr/simple/")
self.assertEqual(response.content, b"Oui")
- def test_unprefixed_language_other_than_accept_language(self):
+ def test_unprefixed_language_with_accept_language(self):
+ """'Accept-Language' is respected."""
response = self.client.get("/simple/", HTTP_ACCEPT_LANGUAGE="fr")
+ self.assertRedirects(response, "/fr/simple/")
+
+ def test_unprefixed_language_with_cookie_language(self):
+ """A language set in the cookies is respected."""
+ self.client.cookies.load({settings.LANGUAGE_COOKIE_NAME: "fr"})
+ response = self.client.get("/simple/")
+ self.assertRedirects(response, "/fr/simple/")
+
+ def test_unprefixed_language_with_non_valid_language(self):
+ response = self.client.get("/simple/", HTTP_ACCEPT_LANGUAGE="fi")
+ self.assertEqual(response.content, b"Yes")
+ self.client.cookies.load({settings.LANGUAGE_COOKIE_NAME: "fi"})
+ response = self.client.get("/simple/")
self.assertEqual(response.content, b"Yes")
def test_page_with_dash(self):
@@ -2214,10 +2228,7 @@ class CountrySpecificLanguageTests(SimpleTestCase):
def test_get_language_from_request_null(self):
lang = trans_null.get_language_from_request(None)
- self.assertEqual(lang, "en")
- with override_settings(LANGUAGE_CODE="de"):
- lang = trans_null.get_language_from_request(None)
- self.assertEqual(lang, "de")
+ self.assertEqual(lang, None)
def test_specific_language_codes(self):
# issue 11915