Fixed #18040 -- Removed so-called project-level locale trees from the list of paths the translation loading process takes in account.

Deprecated in Django 1.3. Removed completely for Django 1.5.

Thanks Claude for the review.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@17861 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Ramiro Morales 2012-03-31 22:24:24 +00:00
parent f38cf60c35
commit b41ebcf1b9
8 changed files with 3 additions and 112 deletions

View File

@ -1,12 +1,8 @@
""" """
Internationalization support. Internationalization support.
""" """
import warnings
from os import path
from django.utils.encoding import force_unicode from django.utils.encoding import force_unicode
from django.utils.functional import lazy from django.utils.functional import lazy
from django.utils.importlib import import_module
__all__ = [ __all__ = [
@ -47,20 +43,6 @@ class Trans(object):
from django.conf import settings from django.conf import settings
if settings.USE_I18N: if settings.USE_I18N:
from django.utils.translation import trans_real as trans from django.utils.translation import trans_real as trans
# Make sure the project's locale dir isn't in LOCALE_PATHS
if settings.SETTINGS_MODULE is not None:
parts = settings.SETTINGS_MODULE.split('.')
project = import_module(parts[0])
project_locale_path = path.normpath(
path.join(path.dirname(project.__file__), 'locale'))
normalized_locale_paths = [path.normpath(locale_path)
for locale_path in settings.LOCALE_PATHS]
if (path.isdir(project_locale_path) and
not project_locale_path in normalized_locale_paths):
warnings.warn("Translations in the project directory "
"aren't supported anymore. Use the "
"LOCALE_PATHS setting instead.",
DeprecationWarning)
else: else:
from django.utils.translation import trans_null as trans from django.utils.translation import trans_null as trans
setattr(self, real_name, getattr(trans, real_name)) setattr(self, real_name, getattr(trans, real_name))

View File

@ -111,13 +111,6 @@ def translation(language):
globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale') globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
if settings.SETTINGS_MODULE is not None:
parts = settings.SETTINGS_MODULE.split('.')
project = import_module(parts[0])
projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')
else:
projectpath = None
def _fetch(lang, fallback=None): def _fetch(lang, fallback=None):
global _translations global _translations
@ -163,11 +156,6 @@ def translation(language):
if os.path.isdir(apppath): if os.path.isdir(apppath):
res = _merge(apppath) res = _merge(apppath)
localepaths = [os.path.normpath(path) for path in settings.LOCALE_PATHS]
if (projectpath and os.path.isdir(projectpath) and
os.path.normpath(projectpath) not in localepaths):
res = _merge(projectpath)
for localepath in reversed(settings.LOCALE_PATHS): for localepath in reversed(settings.LOCALE_PATHS):
if os.path.isdir(localepath): if os.path.isdir(localepath):
res = _merge(localepath) res = _merge(localepath)

View File

@ -1503,18 +1503,9 @@ translations for the same literal:
2. Then, it looks for and uses if it exists a ``locale`` directory in each 2. Then, it looks for and uses if it exists a ``locale`` directory in each
of the installed apps listed in :setting:`INSTALLED_APPS`. The ones of the installed apps listed in :setting:`INSTALLED_APPS`. The ones
appearing first have higher precedence than the ones appearing later. appearing first have higher precedence than the ones appearing later.
3. Then, it looks for a ``locale`` directory in the project directory, or 3. Finally, the Django-provided base translation in ``django/conf/locale``
more accurately, in the directory containing your settings file.
4. Finally, the Django-provided base translation in ``django/conf/locale``
is used as a fallback. is used as a fallback.
.. deprecated:: 1.3
Lookup in the ``locale`` subdirectory of the directory containing your
settings file (item 3 above) is deprecated since the 1.3 release and will be
removed in Django 1.5. You can use the :setting:`LOCALE_PATHS` setting
instead, by listing the absolute filesystem path of such ``locale``
directory in the setting value.
.. seealso:: .. seealso::
The translations for literals included in JavaScript assets are looked up The translations for literals included in JavaScript assets are looked up
@ -1527,25 +1518,14 @@ be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
etc. etc.
This way, you can write applications that include their own translations, and This way, you can write applications that include their own translations, and
you can override base translations in your project path. Or, you can just build you can override base translations in your project. Or, you can just build
a big project out of several apps and put all translations into one big common a big project out of several apps and put all translations into one big common
message file specific to the project you are composing. The choice is yours. message file specific to the project you are composing. The choice is yours.
.. note::
If you're using manually configured settings, as described in
:ref:`settings-without-django-settings-module`, the ``locale`` directory in
the project directory will not be examined, since Django loses the ability
to work out the location of the project directory. (Django normally uses the
location of the settings file to determine this, and a settings file doesn't
exist if you're manually configuring your settings.)
All message file repositories are structured the same way. They are: All message file repositories are structured the same way. They are:
* All paths listed in :setting:`LOCALE_PATHS` in your settings file are * All paths listed in :setting:`LOCALE_PATHS` in your settings file are
searched for ``<language>/LC_MESSAGES/django.(po|mo)`` searched for ``<language>/LC_MESSAGES/django.(po|mo)``
* ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` --
deprecated, see above.
* ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
* ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)`` * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``

View File

@ -157,16 +157,6 @@ class AdminScriptTestCase(unittest.TestCase):
def assertNoOutput(self, stream): def assertNoOutput(self, stream):
"Utility assertion: assert that the given stream is empty" "Utility assertion: assert that the given stream is empty"
# HACK: Under Windows, ignore warnings of the form:
# 'warning: Not loading directory '...\tests\regressiontests\locale': missing __init__.py'
# It has been impossible to filter them out using other means like:
# * Using warning.filterwarnings() (for the Python interpreter running the
# tests) and/or
# * Using -Wignore:... (for the python interpreter spawned in self.run_test())
# Instead use a strategy copied from Mercurial's setup.py
if sys.platform == 'win32':
stream = [e for e in stream.splitlines()
if not e.startswith('warning: Not importing directory')]
self.assertEqual(len(stream), 0, "Stream should be empty: actually contains '%s'" % stream) self.assertEqual(len(stream), 0, "Stream should be empty: actually contains '%s'" % stream)
def assertOutput(self, stream, msg): def assertOutput(self, stream, msg):

View File

@ -40,7 +40,6 @@ from .patterns.tests import (URLRedirectWithoutTrailingSlashTests,
URLTranslationTests, URLDisabledTests, URLTagTests, URLTestCaseBase, URLTranslationTests, URLDisabledTests, URLTagTests, URLTestCaseBase,
URLRedirectWithoutTrailingSlashSettingTests, URLNamespaceTests, URLRedirectWithoutTrailingSlashSettingTests, URLNamespaceTests,
URLPrefixTests, URLResponseTests, URLRedirectTests, PathUnusedTests) URLPrefixTests, URLResponseTests, URLRedirectTests, PathUnusedTests)
from .test_warnings import DeprecationWarningTests
here = os.path.dirname(os.path.abspath(__file__)) here = os.path.dirname(os.path.abspath(__file__))
@ -869,29 +868,6 @@ class LocalePathsResolutionOrderI18NTests(ResolutionOrderI18NTests):
with self.settings(INSTALLED_APPS=extended_apps): with self.settings(INSTALLED_APPS=extended_apps):
self.assertUgettext('Time', 'LOCALE_PATHS') self.assertUgettext('Time', 'LOCALE_PATHS')
def test_locale_paths_override_project_translation(self):
with self.settings(SETTINGS_MODULE='regressiontests'):
self.assertUgettext('Date/time', 'LOCALE_PATHS')
class ProjectResolutionOrderI18NTests(ResolutionOrderI18NTests):
def setUp(self):
self.old_settings_module = settings.SETTINGS_MODULE
settings.SETTINGS_MODULE = 'regressiontests'
super(ProjectResolutionOrderI18NTests, self).setUp()
def tearDown(self):
settings.SETTINGS_MODULE = self.old_settings_module
super(ProjectResolutionOrderI18NTests, self).tearDown()
def test_project_translation(self):
self.assertUgettext('Date/time', 'PROJECT')
def test_project_override_app_translation(self):
extended_apps = list(settings.INSTALLED_APPS) + ['regressiontests.i18n.resolution']
with self.settings(INSTALLED_APPS=extended_apps):
self.assertUgettext('Date/time', 'PROJECT')
class DjangoFallbackResolutionOrderI18NTests(ResolutionOrderI18NTests): class DjangoFallbackResolutionOrderI18NTests(ResolutionOrderI18NTests):
def test_django_fallback(self): def test_django_fallback(self):

View File

@ -1,25 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: django tests\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-02-14 17:33+0100\n"
"PO-Revision-Date: 2011-02-07 13:13-0300\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: models.py:3
msgid "Time"
msgstr "Zeit (PROJECT)"
#: models.py:5
msgid "Date/time"
msgstr "Datum/Zeit (PROJECT)"

View File

@ -25,7 +25,7 @@ REGRESSION_TEST_DIR = os.path.join(RUNTESTS_DIR, REGRESSION_TESTS_DIR_NAME)
TEMP_DIR = tempfile.mkdtemp(prefix='django_') TEMP_DIR = tempfile.mkdtemp(prefix='django_')
os.environ['DJANGO_TEST_TEMP_DIR'] = TEMP_DIR os.environ['DJANGO_TEST_TEMP_DIR'] = TEMP_DIR
REGRESSION_SUBDIRS_TO_SKIP = ['locale'] REGRESSION_SUBDIRS_TO_SKIP = []
ALWAYS_INSTALLED_APPS = [ ALWAYS_INSTALLED_APPS = [
'django.contrib.contenttypes', 'django.contrib.contenttypes',