Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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.
  • Loading branch information...
commit 8c98f39624a60c63a16e097b64e5f71ecc27271f 1 parent c679cb7
@sergeykolosov sergeykolosov authored timgraham committed
View
6 django/conf/global_settings.py
@@ -140,7 +140,13 @@
# 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
5 django/views/i18n.py
@@ -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
62 docs/ref/settings.txt
@@ -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
4 docs/releases/1.7.txt
@@ -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
14 docs/topics/i18n/translation.txt
@@ -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
19 tests/view_tests/tests/test_i18n.py
@@ -51,6 +51,25 @@ def test_setlang_unsafe_next(self):
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']:
Please sign in to comment.
Something went wrong with that request. Please try again.