Fixed #24073 -- Deactivated translations when leave_locale_alone is False

Thanks Tim Graham and Markus Holtermann for the reviews.
This commit is contained in:
Claude Paroz 2015-01-03 20:27:18 +01:00
parent 2c0f64b5f6
commit f7c287fca9
4 changed files with 31 additions and 18 deletions

View File

@ -205,21 +205,20 @@ class BaseCommand(object):
``leave_locale_alone`` ``leave_locale_alone``
A boolean indicating whether the locale set in settings should be A boolean indicating whether the locale set in settings should be
preserved during the execution of the command instead of being preserved during the execution of the command instead of translations
forcibly set to 'en-us'. being deactivated.
Default value is ``False``. Default value is ``False``.
Make sure you know what you are doing if you decide to change the value 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 of this option in your custom command if it creates database content
that is locale-sensitive and such content shouldn't contain any that is locale-sensitive and such content shouldn't contain any
translations (like it happens e.g. with django.contrim.auth translations (like it happens e.g. with django.contrib.auth
permissions) as making the locale differ from the de facto default permissions) as activating any locale might cause unintended effects.
'en-us' might cause unintended effects.
This option can't be False when the can_import_settings option is set 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 to False too because attempting to deactivate translations needs access
settings. This condition will generate a CommandError. to settings. This condition will generate a CommandError.
""" """
# Metadata about this command. # Metadata about this command.
option_list = () option_list = ()
@ -430,12 +429,12 @@ class BaseCommand(object):
"(%s) and 'can_import_settings' (%s) command " "(%s) and 'can_import_settings' (%s) command "
"options." % (self.leave_locale_alone, "options." % (self.leave_locale_alone,
self.can_import_settings)) 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 # content like permissions, and those shouldn't contain any
# translations. # translations.
from django.utils import translation from django.utils import translation
saved_locale = translation.get_language() saved_locale = translation.get_language()
translation.activate('en-us') translation.deactivate_all()
try: try:
if (self.requires_system_checks and if (self.requires_system_checks and

View File

@ -145,13 +145,18 @@ default options such as :djadminopt:`--verbosity` and :djadminopt:`--traceback`.
Management commands and locales Management commands and locales
=============================== ===============================
By default, the :meth:`BaseCommand.execute` method sets the hardcoded 'en-us' By default, the :meth:`BaseCommand.execute` method deactivates translations
locale because some commands shipped with Django perform several tasks because some commands shipped with Django perform several tasks (for example,
(for example, user-facing content rendering and database population) that user-facing content rendering and database population) that require a
require a system-neutral string language (for which we use 'en-us'). project-neutral string language.
If, for some reason, your custom management command needs to use a fixed locale .. versionchanged:: 1.8
different from 'en-us', you should manually activate and deactivate it in your
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 :meth:`~BaseCommand.handle` method using the functions provided by the I18N
support code:: support code::
@ -177,7 +182,7 @@ support code::
translation.deactivate() translation.deactivate()
Another need might be that your command simply should use the locale set in 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. it by using the :data:`BaseCommand.leave_locale_alone` option.
When working on the scenarios described above though, take into account that When working on the scenarios described above though, take into account that
@ -187,7 +192,7 @@ non-uniform locales, so you might need to:
* Make sure the :setting:`USE_I18N` setting is always ``True`` when running * Make sure the :setting:`USE_I18N` setting is always ``True`` when running
the command (this is a good example of the potential problems stemming the command (this is a good example of the potential problems stemming
from a dynamic runtime environment that Django commands avoid offhand by 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 * Review the code of your command and the code it calls for behavioral
differences when locales are changed and evaluate its impact on differences when locales are changed and evaluate its impact on

View File

@ -1014,6 +1014,13 @@ Miscellaneous
that Django includes) will no longer convert null values back to an empty that Django includes) will no longer convert null values back to an empty
string. This is consistent with other backends. 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: .. _deprecated-features-1.8:
Features deprecated in 1.8 Features deprecated in 1.8

View File

@ -2,6 +2,7 @@ import os
from django.apps import apps from django.apps import apps
from django.db import connection from django.db import connection
from django.conf import settings
from django.core import management from django.core import management
from django.core.management import BaseCommand, CommandError, find_commands from django.core.management import BaseCommand, CommandError, find_commands
from django.core.management.utils import find_command, popen_wrapper from django.core.management.utils import find_command, popen_wrapper
@ -52,7 +53,8 @@ class CommandTests(SimpleTestCase):
out = StringIO() out = StringIO()
with translation.override('pl'): with translation.override('pl'):
management.call_command('leave_locale_alone_false', stdout=out) 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): def test_configured_locale_preserved(self):
# Leaves locale from settings when set to false # Leaves locale from settings when set to false