Fixed #15318 -- Added settings for language cookie max-age, path, domain

Introduced a number of settings to configure max-age, path, and domain
for the language cookie: LANGUAGE_COOKIE_AGE, LANGUAGE_COOKIE_PATH and
LANGUAGE_COOKIE_DOMAIN.

Thanks sahid for the suggestion.
This commit is contained in:
Sergey Kolosov 2013-05-19 12:20:34 +02:00 committed by Tim Graham
parent c679cb7f60
commit 8c98f39624
6 changed files with 109 additions and 1 deletions

View File

@ -140,7 +140,13 @@ LANGUAGES_BIDI = ("he", "ar", "fa", "ur")
# to load the internationalization machinery.
USE_I18N = True
LOCALE_PATHS = ()
# Settings for language cookie
LANGUAGE_COOKIE_NAME = 'django_language'
LANGUAGE_COOKIE_AGE = None
LANGUAGE_COOKIE_DOMAIN = None
LANGUAGE_COOKIE_PATH = '/'
# If you set this to True, Django will format dates, numbers and calendars
# according to user current locale.

View File

@ -38,7 +38,10 @@ def set_language(request):
if hasattr(request, 'session'):
request.session[LANGUAGE_SESSION_KEY] = lang_code
else:
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code,
max_age=settings.LANGUAGE_COOKIE_AGE,
path=settings.LANGUAGE_COOKIE_PATH,
domain=settings.LANGUAGE_COOKIE_DOMAIN)
return response

View File

@ -1362,6 +1362,40 @@ See :ref:`how-django-discovers-language-preference` for more details.
.. _list of language identifiers: http://www.i18nguy.com/unicode/language-identifiers.html
.. setting:: LANGUAGE_COOKIE_AGE
LANGUAGE_COOKIE_AGE
-------------------
.. versionadded:: 1.7
Default: ``None`` (expires at browser close)
The age of the language cookie, in seconds.
.. setting:: LANGUAGE_COOKIE_DOMAIN
LANGUAGE_COOKIE_DOMAIN
----------------------
.. versionadded:: 1.7
Default: ``None``
The domain to use for the language cookie. Set this to a string such as
``".example.com"`` (note the leading dot!) for cross-domain cookies, or use
``None`` for a standard domain cookie.
Be cautious when updating this setting on a production site. If you update
this setting to enable cross-domain cookies on a site that previously used
standard domain cookies, existing user cookies that have the old domain
will not be updated. This will result in site users being unable to switch
the language as long as these cookies persist. The only safe and reliable
option to perform the switch is to change the language cookie name
permanently (via the :setting:`SESSION_COOKIE_NAME` setting) and to add
a middleware that copies the value from the old cookie to a new one and then
deletes the old one.
.. setting:: LANGUAGE_COOKIE_NAME
LANGUAGE_COOKIE_NAME
@ -1373,6 +1407,31 @@ The name of the cookie to use for the language cookie. This can be whatever
you want (but should be different from :setting:`SESSION_COOKIE_NAME`). See
:doc:`/topics/i18n/index`.
.. setting:: LANGUAGE_COOKIE_PATH
LANGUAGE_COOKIE_PATH
--------------------
.. versionadded:: 1.7
Default: ``/``
The path set on the language cookie. This should either match the URL path of your
Django installation or be a parent of that path.
This is useful if you have multiple Django instances running under the same
hostname. They can use different cookie paths and each instance will only see
its own language cookie.
Be cautious when updating this setting on a production site. If you update this
setting to use a deeper path than it previously used, existing user cookies that
have the old path will not be updated. This will result in site users being
unable to switch the language as long as these cookies persist. The only safe
and reliable option to perform the switch is to change the language cookie name
permanently (via the :setting:`SESSION_COOKIE_NAME` setting), and to add
a middleware that copies the value from the old cookie to a new one and then
deletes the one.
.. setting:: LANGUAGES
LANGUAGES
@ -2801,7 +2860,10 @@ Globalization (i18n/l10n)
* :setting:`FIRST_DAY_OF_WEEK`
* :setting:`FORMAT_MODULE_PATH`
* :setting:`LANGUAGE_CODE`
* :setting:`LANGUAGE_COOKIE_AGE`
* :setting:`LANGUAGE_COOKIE_DOMAIN`
* :setting:`LANGUAGE_COOKIE_NAME`
* :setting:`LANGUAGE_COOKIE_PATH`
* :setting:`LANGUAGES`
* :setting:`LOCALE_PATHS`
* :setting:`MONTH_DAY_FORMAT`

View File

@ -559,6 +559,10 @@ Internationalization
app or project message file. See :ref:`how-to-create-language-files` for
details.
* The following settings to adjust the language cookie options were introduced:
:setting:`LANGUAGE_COOKIE_AGE`, :setting:`LANGUAGE_COOKIE_DOMAIN`
and :setting:`LANGUAGE_COOKIE_PATH`.
* Added :ref:`format definitions <format-localization>` for Esperanto.
Management Commands

View File

@ -1575,6 +1575,20 @@ which returns the language used in the current thread,
for the current thread, and ``django.utils.translation.check_for_language()``
which checks if the given language is supported by Django.
Language cookie
---------------
A number of settings can be used to adjust language cookie options:
* :setting:`LANGUAGE_COOKIE_NAME`
.. versionadded:: 1.7
* :setting:`LANGUAGE_COOKIE_AGE`
* :setting:`LANGUAGE_COOKIE_DOMAIN`
* :setting:`LANGUAGE_COOKIE_PATH`
Implementation notes
====================

View File

@ -51,6 +51,25 @@ class I18NTests(TestCase):
def test_setlang_reversal(self):
self.assertEqual(reverse('set_language'), '/i18n/setlang/')
def test_setlang_cookie(self):
# we force saving language to a cookie rather than a session
# by excluding session middleware and those which do require it
test_settings = dict(
MIDDLEWARE_CLASSES=('django.middleware.common.CommonMiddleware',),
LANGUAGE_COOKIE_NAME='mylanguage',
LANGUAGE_COOKIE_AGE=3600 * 7 * 2,
LANGUAGE_COOKIE_DOMAIN='.example.com',
LANGUAGE_COOKIE_PATH='/test/',
)
with self.settings(**test_settings):
post_data = dict(language='pl', next='/views/')
response = self.client.post('/i18n/setlang/', data=post_data)
language_cookie = response.cookies.get('mylanguage')
self.assertEqual(language_cookie.value, 'pl')
self.assertEqual(language_cookie['domain'], '.example.com')
self.assertEqual(language_cookie['path'], '/test/')
self.assertEqual(language_cookie['max-age'], 3600 * 7 * 2)
def test_jsi18n(self):
"""The javascript_catalog can be deployed with language settings"""
for lang_code in ['es', 'fr', 'ru']: