mirror of
https://github.com/django/django.git
synced 2025-06-05 11:39:13 +00:00
Refs #15902 -- Stopped set_language() storing user's language in the session.
Per deprecation timeline.
This commit is contained in:
parent
52a238ddf2
commit
d134b0b93e
@ -1,7 +1,6 @@
|
|||||||
import base64
|
import base64
|
||||||
import logging
|
import logging
|
||||||
import string
|
import string
|
||||||
import warnings
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -12,9 +11,7 @@ from django.utils import timezone
|
|||||||
from django.utils.crypto import (
|
from django.utils.crypto import (
|
||||||
constant_time_compare, get_random_string, salted_hmac,
|
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.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
|
# session_key should not be case sensitive because some backends can store it
|
||||||
# on case insensitive file systems.
|
# on case insensitive file systems.
|
||||||
@ -55,13 +52,6 @@ class SessionBase:
|
|||||||
return key in self._session
|
return key in self._session
|
||||||
|
|
||||||
def __getitem__(self, key):
|
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]
|
return self._session[key]
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
|
@ -17,11 +17,8 @@ __all__ = [
|
|||||||
'ngettext', 'ngettext_lazy',
|
'ngettext', 'ngettext_lazy',
|
||||||
'pgettext', 'pgettext_lazy',
|
'pgettext', 'pgettext_lazy',
|
||||||
'npgettext', 'npgettext_lazy',
|
'npgettext', 'npgettext_lazy',
|
||||||
'LANGUAGE_SESSION_KEY',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
LANGUAGE_SESSION_KEY = '_language'
|
|
||||||
|
|
||||||
|
|
||||||
class TranslatorCommentWarning(SyntaxWarning):
|
class TranslatorCommentWarning(SyntaxWarning):
|
||||||
pass
|
pass
|
||||||
|
@ -11,9 +11,7 @@ from django.template import Context, Engine
|
|||||||
from django.urls import translate_url
|
from django.urls import translate_url
|
||||||
from django.utils.formats import get_format
|
from django.utils.formats import get_format
|
||||||
from django.utils.http import url_has_allowed_host_and_scheme
|
from django.utils.http import url_has_allowed_host_and_scheme
|
||||||
from django.utils.translation import (
|
from django.utils.translation import check_for_language, get_language
|
||||||
LANGUAGE_SESSION_KEY, check_for_language, get_language,
|
|
||||||
)
|
|
||||||
from django.utils.translation.trans_real import DjangoTranslation
|
from django.utils.translation.trans_real import DjangoTranslation
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
|
||||||
@ -57,10 +55,6 @@ def set_language(request):
|
|||||||
next_trans = translate_url(next_url, lang_code)
|
next_trans = translate_url(next_url, lang_code)
|
||||||
if next_trans != next_url:
|
if next_trans != next_url:
|
||||||
response = HttpResponseRedirect(next_trans)
|
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(
|
response.set_cookie(
|
||||||
settings.LANGUAGE_COOKIE_NAME, lang_code,
|
settings.LANGUAGE_COOKIE_NAME, lang_code,
|
||||||
max_age=settings.LANGUAGE_COOKIE_AGE,
|
max_age=settings.LANGUAGE_COOKIE_AGE,
|
||||||
|
@ -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``.
|
Turns a Django template into something that is understood by ``xgettext``.
|
||||||
It does so by translating the Django translation tags into standard
|
It does so by translating the Django translation tags into standard
|
||||||
``gettext`` function invocations.
|
``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.
|
|
||||||
|
@ -663,12 +663,11 @@ Internationalization
|
|||||||
|
|
||||||
* The :class:`~django.middleware.locale.LocaleMiddleware` now stores the user's
|
* The :class:`~django.middleware.locale.LocaleMiddleware` now stores the user's
|
||||||
selected language with the session key ``_language``. This should only be
|
selected language with the session key ``_language``. This should only be
|
||||||
accessed using the :data:`~django.utils.translation.LANGUAGE_SESSION_KEY`
|
accessed using the ``LANGUAGE_SESSION_KEY`` constant. Previously it was
|
||||||
constant. Previously it was stored with the key ``django_language`` and the
|
stored with the key ``django_language`` and the ``LANGUAGE_SESSION_KEY``
|
||||||
``LANGUAGE_SESSION_KEY`` constant did not exist, but keys reserved for Django
|
constant did not exist, but keys reserved for Django should start with an
|
||||||
should start with an underscore. For backwards compatibility ``django_language``
|
underscore. For backwards compatibility ``django_language`` is still read
|
||||||
is still read from in 1.7. Sessions will be migrated to the new key
|
from in 1.7. Sessions will be migrated to the new key as they are written.
|
||||||
as they are written.
|
|
||||||
|
|
||||||
* The :ttag:`blocktrans` tag now supports a ``trimmed`` option. This
|
* The :ttag:`blocktrans` tag now supports a ``trimmed`` option. This
|
||||||
option will remove newline characters from the beginning and the end of the
|
option will remove newline characters from the beginning and the end of the
|
||||||
|
@ -254,6 +254,9 @@ to remove usage of these features.
|
|||||||
* ``django.utils.translation.ugettext()``, ``ugettext_lazy()``,
|
* ``django.utils.translation.ugettext()``, ``ugettext_lazy()``,
|
||||||
``ugettext_noop()``, ``ungettext()``, and ``ungettext_lazy()`` are removed.
|
``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
|
See :ref:`deprecated-features-3.1` for details on these changes, including how
|
||||||
to remove usage of these features.
|
to remove usage of these features.
|
||||||
|
|
||||||
|
@ -29,11 +29,10 @@ from django.utils.formats import (
|
|||||||
from django.utils.numberformat import format as nformat
|
from django.utils.numberformat import format as nformat
|
||||||
from django.utils.safestring import SafeString, mark_safe
|
from django.utils.safestring import SafeString, mark_safe
|
||||||
from django.utils.translation import (
|
from django.utils.translation import (
|
||||||
LANGUAGE_SESSION_KEY, activate, check_for_language, deactivate,
|
activate, check_for_language, deactivate, get_language, get_language_bidi,
|
||||||
get_language, get_language_bidi, get_language_from_request,
|
get_language_from_request, get_language_info, gettext, gettext_lazy,
|
||||||
get_language_info, gettext, gettext_lazy, ngettext, ngettext_lazy,
|
ngettext, ngettext_lazy, npgettext, npgettext_lazy, pgettext,
|
||||||
npgettext, npgettext_lazy, pgettext, round_away_from_one, to_language,
|
round_away_from_one, to_language, to_locale, trans_null, trans_real,
|
||||||
to_locale, trans_null, trans_real,
|
|
||||||
)
|
)
|
||||||
from django.utils.translation.reloader import (
|
from django.utils.translation.reloader import (
|
||||||
translation_file_changed, watch_for_translation_changes,
|
translation_file_changed, watch_for_translation_changes,
|
||||||
@ -1684,21 +1683,6 @@ class LocaleMiddlewareTests(TestCase):
|
|||||||
response = self.client.get('/en/streaming/')
|
response = self.client.get('/en/streaming/')
|
||||||
self.assertContains(response, "Yes/No")
|
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(
|
@override_settings(
|
||||||
USE_I18N=True,
|
USE_I18N=True,
|
||||||
|
@ -4,15 +4,12 @@ from os import path
|
|||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.test import (
|
from django.test import (
|
||||||
RequestFactory, SimpleTestCase, TestCase, ignore_warnings, modify_settings,
|
RequestFactory, SimpleTestCase, TestCase, modify_settings,
|
||||||
override_settings,
|
override_settings,
|
||||||
)
|
)
|
||||||
from django.test.selenium import SeleniumTestCase
|
from django.test.selenium import SeleniumTestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.deprecation import RemovedInDjango40Warning
|
from django.utils.translation import get_language, override
|
||||||
from django.utils.translation import (
|
|
||||||
LANGUAGE_SESSION_KEY, get_language, override,
|
|
||||||
)
|
|
||||||
from django.views.i18n import JavaScriptCatalog, get_formats
|
from django.views.i18n import JavaScriptCatalog, get_formats
|
||||||
|
|
||||||
from ..urls import locale_dir
|
from ..urls import locale_dir
|
||||||
@ -37,8 +34,6 @@ class SetLanguageTests(TestCase):
|
|||||||
post_data = {'language': lang_code, 'next': '/'}
|
post_data = {'language': lang_code, 'next': '/'}
|
||||||
response = self.client.post('/i18n/setlang/', post_data, HTTP_REFERER='/i_should_not_be_used/')
|
response = self.client.post('/i18n/setlang/', post_data, HTTP_REFERER='/i_should_not_be_used/')
|
||||||
self.assertRedirects(response, '/')
|
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.
|
# The language is set in a cookie.
|
||||||
language_cookie = self.client.cookies[settings.LANGUAGE_COOKIE_NAME]
|
language_cookie = self.client.cookies[settings.LANGUAGE_COOKIE_NAME]
|
||||||
self.assertEqual(language_cookie.value, lang_code)
|
self.assertEqual(language_cookie.value, lang_code)
|
||||||
@ -59,8 +54,6 @@ class SetLanguageTests(TestCase):
|
|||||||
response = self.client.post('/i18n/setlang/', data=post_data)
|
response = self.client.post('/i18n/setlang/', data=post_data)
|
||||||
self.assertEqual(response.url, '/')
|
self.assertEqual(response.url, '/')
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
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):
|
def test_setlang_http_next(self):
|
||||||
"""
|
"""
|
||||||
@ -74,14 +67,10 @@ class SetLanguageTests(TestCase):
|
|||||||
response = self.client.post('/i18n/setlang/', data=post_data, secure=True)
|
response = self.client.post('/i18n/setlang/', data=post_data, secure=True)
|
||||||
self.assertEqual(response.url, '/')
|
self.assertEqual(response.url, '/')
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
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.
|
# Insecure URL in HTTP referer.
|
||||||
response = self.client.post('/i18n/setlang/', secure=True, HTTP_REFERER=non_https_next_url)
|
response = self.client.post('/i18n/setlang/', secure=True, HTTP_REFERER=non_https_next_url)
|
||||||
self.assertEqual(response.url, '/')
|
self.assertEqual(response.url, '/')
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
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):
|
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/')
|
response = self.client.post('/i18n/setlang/', post_data, HTTP_REFERER='/i18n/')
|
||||||
self.assertRedirects(response, '/i18n/', fetch_redirect_response=False)
|
self.assertRedirects(response, '/i18n/', fetch_redirect_response=False)
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
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):
|
def test_setlang_default_redirect(self):
|
||||||
"""
|
"""
|
||||||
@ -106,8 +93,6 @@ class SetLanguageTests(TestCase):
|
|||||||
response = self.client.post('/i18n/setlang/', post_data)
|
response = self.client.post('/i18n/setlang/', post_data)
|
||||||
self.assertRedirects(response, '/')
|
self.assertRedirects(response, '/')
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
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):
|
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')
|
response = self.client.post('/i18n/setlang/', post_data, HTTP_ACCEPT='application/json')
|
||||||
self.assertRedirects(response, '/')
|
self.assertRedirects(response, '/')
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
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):
|
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)
|
response = self.client.post('/i18n/setlang/', post_data, **headers)
|
||||||
self.assertEqual(response.status_code, 204)
|
self.assertEqual(response.status_code, 204)
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
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):
|
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')
|
response = self.client.post('/i18n/setlang/', post_data, HTTP_ACCEPT='application/json')
|
||||||
self.assertEqual(response.status_code, 204)
|
self.assertEqual(response.status_code, 204)
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
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):
|
def test_setlang_unsafe_next_for_ajax(self):
|
||||||
"""
|
"""
|
||||||
@ -160,15 +139,6 @@ class SetLanguageTests(TestCase):
|
|||||||
self.assertEqual(response.url, '/')
|
self.assertEqual(response.url, '/')
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
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):
|
def test_setlang_reversal(self):
|
||||||
self.assertEqual(reverse('set_language'), '/i18n/setlang/')
|
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)
|
response = self.client.post('/i18n/setlang/', {'language': lang_code}, HTTP_REFERER=encoded_url)
|
||||||
self.assertRedirects(response, encoded_url, fetch_redirect_response=False)
|
self.assertRedirects(response, encoded_url, fetch_redirect_response=False)
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
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={
|
@modify_settings(MIDDLEWARE={
|
||||||
'append': 'django.middleware.locale.LocaleMiddleware',
|
'append': 'django.middleware.locale.LocaleMiddleware',
|
||||||
@ -220,8 +188,6 @@ class SetLanguageTests(TestCase):
|
|||||||
follow=True, HTTP_REFERER='/en/translated/'
|
follow=True, HTTP_REFERER='/en/translated/'
|
||||||
)
|
)
|
||||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, 'nl')
|
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/')
|
self.assertRedirects(response, '/nl/vertaald/')
|
||||||
# And reverse
|
# And reverse
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user