Skip to content

Commit

Permalink
Fixed #24073 -- Deactivated translations when leave_locale_alone is F…
Browse files Browse the repository at this point in the history
…alse

Thanks Tim Graham and Markus Holtermann for the reviews.
  • Loading branch information
claudep committed Jan 7, 2015
1 parent 2c0f64b commit f7c287f
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 18 deletions.
17 changes: 8 additions & 9 deletions django/core/management/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,21 +205,20 @@ class BaseCommand(object):
``leave_locale_alone``
A boolean indicating whether the locale set in settings should be
preserved during the execution of the command instead of being
forcibly set to 'en-us'.
preserved during the execution of the command instead of translations
being deactivated.
Default value is ``False``.
Make sure you know what you are doing if you decide to change the value
of this option in your custom command if it creates database content
that is locale-sensitive and such content shouldn't contain any
translations (like it happens e.g. with django.contrim.auth
permissions) as making the locale differ from the de facto default
'en-us' might cause unintended effects.
translations (like it happens e.g. with django.contrib.auth
permissions) as activating any locale might cause unintended effects.
This option can't be False when the can_import_settings option is set
to False too because attempting to set the locale needs access to
settings. This condition will generate a CommandError.
to False too because attempting to deactivate translations needs access
to settings. This condition will generate a CommandError.
"""
# Metadata about this command.
option_list = ()
Expand Down Expand Up @@ -430,12 +429,12 @@ def execute(self, *args, **options):
"(%s) and 'can_import_settings' (%s) command "
"options." % (self.leave_locale_alone,
self.can_import_settings))
# Switch to US English, because django-admin creates database
# Deactivate translations, because django-admin creates database
# content like permissions, and those shouldn't contain any
# translations.
from django.utils import translation
saved_locale = translation.get_language()
translation.activate('en-us')
translation.deactivate_all()

try:
if (self.requires_system_checks and
Expand Down
21 changes: 13 additions & 8 deletions docs/howto/custom-management-commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,18 @@ default options such as :djadminopt:`--verbosity` and :djadminopt:`--traceback`.
Management commands and locales
===============================

By default, the :meth:`BaseCommand.execute` method sets the hardcoded 'en-us'
locale because some commands shipped with Django perform several tasks
(for example, user-facing content rendering and database population) that
require a system-neutral string language (for which we use 'en-us').
By default, the :meth:`BaseCommand.execute` method deactivates translations
because some commands shipped with Django perform several tasks (for example,
user-facing content rendering and database population) that require a
project-neutral string language.

If, for some reason, your custom management command needs to use a fixed locale
different from 'en-us', you should manually activate and deactivate it in your
.. versionchanged:: 1.8

In previous versions, Django forced the "en-us" locale instead of
deactivating translations.

If, for some reason, your custom management command needs to use a fixed locale,
you should manually activate and deactivate it in your
:meth:`~BaseCommand.handle` method using the functions provided by the I18N
support code::

Expand All @@ -177,7 +182,7 @@ support code::
translation.deactivate()

Another need might be that your command simply should use the locale set in
settings and Django should be kept from forcing it to 'en-us'. You can achieve
settings and Django should be kept from deactivating it. You can achieve
it by using the :data:`BaseCommand.leave_locale_alone` option.

When working on the scenarios described above though, take into account that
Expand All @@ -187,7 +192,7 @@ non-uniform locales, so you might need to:
* Make sure the :setting:`USE_I18N` setting is always ``True`` when running
the command (this is a good example of the potential problems stemming
from a dynamic runtime environment that Django commands avoid offhand by
always using a fixed locale).
deactivating translations).

* Review the code of your command and the code it calls for behavioral
differences when locales are changed and evaluate its impact on
Expand Down
7 changes: 7 additions & 0 deletions docs/releases/1.8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,13 @@ Miscellaneous
that Django includes) will no longer convert null values back to an empty
string. This is consistent with other backends.

* When the :attr:`~django.core.management.BaseCommand.leave_locale_alone`
attribute is ``False``, translations are now deactivated instead of forcing
the "en-us" locale. In the case your models contained non-English strings and
you counted on English translations to be activated in management commands,
this will not happen any longer. It might be that new database migrations are
generated (once) after migrating to 1.8.

.. _deprecated-features-1.8:

Features deprecated in 1.8
Expand Down
4 changes: 3 additions & 1 deletion tests/user_commands/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from django.apps import apps
from django.db import connection
from django.conf import settings
from django.core import management
from django.core.management import BaseCommand, CommandError, find_commands
from django.core.management.utils import find_command, popen_wrapper
Expand Down Expand Up @@ -52,7 +53,8 @@ def test_default_en_us_locale_set(self):
out = StringIO()
with translation.override('pl'):
management.call_command('leave_locale_alone_false', stdout=out)
self.assertEqual(out.getvalue(), "en-us\n")
# get_language returns settings.LANGUAGE_CODE for NullTranslations instances
self.assertEqual(out.getvalue(), "%s\n" % settings.LANGUAGE_CODE)

def test_configured_locale_preserved(self):
# Leaves locale from settings when set to false
Expand Down

0 comments on commit f7c287f

Please sign in to comment.