From d134b0b93ee10a2128c595997cbc6022c4a982f7 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Wed, 6 Jan 2021 13:16:24 +0100 Subject: [PATCH] Refs #15902 -- Stopped set_language() storing user's language in the session. Per deprecation timeline. --- django/contrib/sessions/backends/base.py | 10 ------- django/utils/translation/__init__.py | 3 -- django/views/i18n.py | 8 +---- docs/ref/utils.txt | 10 ------- docs/releases/1.7.txt | 11 ++++--- docs/releases/4.0.txt | 3 ++ tests/i18n/tests.py | 24 +++------------ tests/view_tests/tests/test_i18n.py | 38 ++---------------------- 8 files changed, 15 insertions(+), 92 deletions(-) diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py index 0f06b23e93..143c08fbef 100644 --- a/django/contrib/sessions/backends/base.py +++ b/django/contrib/sessions/backends/base.py @@ -1,7 +1,6 @@ import base64 import logging import string -import warnings from datetime import datetime, timedelta from django.conf import settings @@ -12,9 +11,7 @@ from django.utils import timezone from django.utils.crypto import ( constant_time_compare, get_random_string, salted_hmac, ) -from django.utils.deprecation import RemovedInDjango40Warning from django.utils.module_loading import import_string -from django.utils.translation import LANGUAGE_SESSION_KEY # session_key should not be case sensitive because some backends can store it # on case insensitive file systems. @@ -55,13 +52,6 @@ class SessionBase: return key in self._session def __getitem__(self, key): - if key == LANGUAGE_SESSION_KEY: - warnings.warn( - 'The user language will no longer be stored in ' - 'request.session in Django 4.0. Read it from ' - 'request.COOKIES[settings.LANGUAGE_COOKIE_NAME] instead.', - RemovedInDjango40Warning, stacklevel=2, - ) return self._session[key] def __setitem__(self, key, value): diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py index 8e6b8ec0f8..aa5cd33f5b 100644 --- a/django/utils/translation/__init__.py +++ b/django/utils/translation/__init__.py @@ -17,11 +17,8 @@ __all__ = [ 'ngettext', 'ngettext_lazy', 'pgettext', 'pgettext_lazy', 'npgettext', 'npgettext_lazy', - 'LANGUAGE_SESSION_KEY', ] -LANGUAGE_SESSION_KEY = '_language' - class TranslatorCommentWarning(SyntaxWarning): pass diff --git a/django/views/i18n.py b/django/views/i18n.py index d6a29eb8f9..ecb30a45f1 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -11,9 +11,7 @@ from django.template import Context, Engine from django.urls import translate_url from django.utils.formats import get_format from django.utils.http import url_has_allowed_host_and_scheme -from django.utils.translation import ( - LANGUAGE_SESSION_KEY, check_for_language, get_language, -) +from django.utils.translation import check_for_language, get_language from django.utils.translation.trans_real import DjangoTranslation from django.views.generic import View @@ -57,10 +55,6 @@ def set_language(request): next_trans = translate_url(next_url, lang_code) if next_trans != next_url: response = HttpResponseRedirect(next_trans) - if hasattr(request, 'session'): - # Storing the language in the session is deprecated. - # (RemovedInDjango40Warning) - request.session[LANGUAGE_SESSION_KEY] = lang_code response.set_cookie( settings.LANGUAGE_COOKIE_NAME, lang_code, max_age=settings.LANGUAGE_COOKIE_AGE, diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index b04e1196d4..52c5101e9f 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -1099,13 +1099,3 @@ For a complete discussion on the usage of the following see the Turns a Django template into something that is understood by ``xgettext``. It does so by translating the Django translation tags into standard ``gettext`` function invocations. - -.. data:: LANGUAGE_SESSION_KEY - - Session key under which the active language for the current session is - stored. - - .. deprecated:: 3.0 - - The language won't be stored in the session in Django 4.0. Use the - :setting:`LANGUAGE_COOKIE_NAME` cookie instead. diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index 6403ae0b51..2841294067 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -663,12 +663,11 @@ Internationalization * The :class:`~django.middleware.locale.LocaleMiddleware` now stores the user's selected language with the session key ``_language``. This should only be - accessed using the :data:`~django.utils.translation.LANGUAGE_SESSION_KEY` - constant. Previously it was stored with the key ``django_language`` and the - ``LANGUAGE_SESSION_KEY`` constant did not exist, but keys reserved for Django - should start with an underscore. For backwards compatibility ``django_language`` - is still read from in 1.7. Sessions will be migrated to the new key - as they are written. + accessed using the ``LANGUAGE_SESSION_KEY`` constant. Previously it was + stored with the key ``django_language`` and the ``LANGUAGE_SESSION_KEY`` + constant did not exist, but keys reserved for Django should start with an + underscore. For backwards compatibility ``django_language`` is still read + from in 1.7. Sessions will be migrated to the new key as they are written. * The :ttag:`blocktrans` tag now supports a ``trimmed`` option. This option will remove newline characters from the beginning and the end of the diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt index b5b4d343aa..43e94a790b 100644 --- a/docs/releases/4.0.txt +++ b/docs/releases/4.0.txt @@ -254,6 +254,9 @@ to remove usage of these features. * ``django.utils.translation.ugettext()``, ``ugettext_lazy()``, ``ugettext_noop()``, ``ungettext()``, and ``ungettext_lazy()`` are removed. +* ``django.views.i18n.set_language()`` doesn't set the user language in + ``request.session`` (key ``_language``). + See :ref:`deprecated-features-3.1` for details on these changes, including how to remove usage of these features. diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index 9498103585..315af09e62 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -29,11 +29,10 @@ from django.utils.formats import ( from django.utils.numberformat import format as nformat from django.utils.safestring import SafeString, mark_safe from django.utils.translation import ( - LANGUAGE_SESSION_KEY, activate, check_for_language, deactivate, - get_language, get_language_bidi, get_language_from_request, - get_language_info, gettext, gettext_lazy, ngettext, ngettext_lazy, - npgettext, npgettext_lazy, pgettext, round_away_from_one, to_language, - to_locale, trans_null, trans_real, + activate, check_for_language, deactivate, get_language, get_language_bidi, + get_language_from_request, get_language_info, gettext, gettext_lazy, + ngettext, ngettext_lazy, npgettext, npgettext_lazy, pgettext, + round_away_from_one, to_language, to_locale, trans_null, trans_real, ) from django.utils.translation.reloader import ( translation_file_changed, watch_for_translation_changes, @@ -1684,21 +1683,6 @@ class LocaleMiddlewareTests(TestCase): response = self.client.get('/en/streaming/') self.assertContains(response, "Yes/No") - @override_settings( - MIDDLEWARE=[ - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'django.middleware.common.CommonMiddleware', - ], - ) - def test_language_not_saved_to_session(self): - """ - The Current language isno' automatically saved to the session on every - request (#21473). - """ - self.client.get('/fr/simple/') - self.assertNotIn(LANGUAGE_SESSION_KEY, self.client.session) - @override_settings( USE_I18N=True, diff --git a/tests/view_tests/tests/test_i18n.py b/tests/view_tests/tests/test_i18n.py index 84dff20753..091df959fc 100644 --- a/tests/view_tests/tests/test_i18n.py +++ b/tests/view_tests/tests/test_i18n.py @@ -4,15 +4,12 @@ from os import path from django.conf import settings from django.test import ( - RequestFactory, SimpleTestCase, TestCase, ignore_warnings, modify_settings, + RequestFactory, SimpleTestCase, TestCase, modify_settings, override_settings, ) from django.test.selenium import SeleniumTestCase from django.urls import reverse -from django.utils.deprecation import RemovedInDjango40Warning -from django.utils.translation import ( - LANGUAGE_SESSION_KEY, get_language, override, -) +from django.utils.translation import get_language, override from django.views.i18n import JavaScriptCatalog, get_formats from ..urls import locale_dir @@ -37,8 +34,6 @@ class SetLanguageTests(TestCase): post_data = {'language': lang_code, 'next': '/'} response = self.client.post('/i18n/setlang/', post_data, HTTP_REFERER='/i_should_not_be_used/') self.assertRedirects(response, '/') - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) # The language is set in a cookie. language_cookie = self.client.cookies[settings.LANGUAGE_COOKIE_NAME] self.assertEqual(language_cookie.value, lang_code) @@ -59,8 +54,6 @@ class SetLanguageTests(TestCase): response = self.client.post('/i18n/setlang/', data=post_data) self.assertEqual(response.url, '/') self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code) - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) def test_setlang_http_next(self): """ @@ -74,14 +67,10 @@ class SetLanguageTests(TestCase): response = self.client.post('/i18n/setlang/', data=post_data, secure=True) self.assertEqual(response.url, '/') self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code) - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) # Insecure URL in HTTP referer. response = self.client.post('/i18n/setlang/', secure=True, HTTP_REFERER=non_https_next_url) self.assertEqual(response.url, '/') self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code) - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) def test_setlang_redirect_to_referer(self): """ @@ -93,8 +82,6 @@ class SetLanguageTests(TestCase): response = self.client.post('/i18n/setlang/', post_data, HTTP_REFERER='/i18n/') self.assertRedirects(response, '/i18n/', fetch_redirect_response=False) self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code) - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) def test_setlang_default_redirect(self): """ @@ -106,8 +93,6 @@ class SetLanguageTests(TestCase): response = self.client.post('/i18n/setlang/', post_data) self.assertRedirects(response, '/') self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code) - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) def test_setlang_performs_redirect_for_ajax_if_explicitly_requested(self): """ @@ -119,8 +104,6 @@ class SetLanguageTests(TestCase): response = self.client.post('/i18n/setlang/', post_data, HTTP_ACCEPT='application/json') self.assertRedirects(response, '/') self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code) - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) def test_setlang_doesnt_perform_a_redirect_to_referer_for_ajax(self): """ @@ -133,8 +116,6 @@ class SetLanguageTests(TestCase): response = self.client.post('/i18n/setlang/', post_data, **headers) self.assertEqual(response.status_code, 204) self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code) - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) def test_setlang_doesnt_perform_a_default_redirect_for_ajax(self): """ @@ -146,8 +127,6 @@ class SetLanguageTests(TestCase): response = self.client.post('/i18n/setlang/', post_data, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 204) self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code) - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) def test_setlang_unsafe_next_for_ajax(self): """ @@ -160,15 +139,6 @@ class SetLanguageTests(TestCase): self.assertEqual(response.url, '/') self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code) - def test_session_language_deprecation(self): - msg = ( - 'The user language will no longer be stored in request.session ' - 'in Django 4.0. Read it from ' - 'request.COOKIES[settings.LANGUAGE_COOKIE_NAME] instead.' - ) - with self.assertRaisesMessage(RemovedInDjango40Warning, msg): - self.client.session[LANGUAGE_SESSION_KEY] - def test_setlang_reversal(self): self.assertEqual(reverse('set_language'), '/i18n/setlang/') @@ -208,8 +178,6 @@ class SetLanguageTests(TestCase): response = self.client.post('/i18n/setlang/', {'language': lang_code}, HTTP_REFERER=encoded_url) self.assertRedirects(response, encoded_url, fetch_redirect_response=False) self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code) - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) @modify_settings(MIDDLEWARE={ 'append': 'django.middleware.locale.LocaleMiddleware', @@ -220,8 +188,6 @@ class SetLanguageTests(TestCase): follow=True, HTTP_REFERER='/en/translated/' ) self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, 'nl') - with ignore_warnings(category=RemovedInDjango40Warning): - self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], 'nl') self.assertRedirects(response, '/nl/vertaald/') # And reverse response = self.client.post(