From 2397daab4a1b95a055514b009818730f4dfc4799 Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Tue, 5 Nov 2013 14:30:31 +0100 Subject: [PATCH] Fixed #9523 -- Restart runserver after compiling apps translations Django also uses locales provided by apps, which also might change. Also when i18n is disabled, there is no need for watching translation files. --- django/utils/autoreload.py | 34 ++++++++++------ tests/utils_tests/test_autoreload.py | 61 ++++++++++++++++++++-------- 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py index 2325d0df80..84aed44495 100644 --- a/django/utils/autoreload.py +++ b/django/utils/autoreload.py @@ -37,6 +37,9 @@ import traceback from django.conf import settings from django.core.signals import request_finished +from django.utils._os import upath +from django.utils.importlib import import_module +from django.utils.translation.trans_real import all_locale_paths from django.utils import six try: from django.utils.six.moves import _thread as thread @@ -97,19 +100,24 @@ def gen_filenames(): filenames = [filename.__file__ for filename in sys.modules.values() if hasattr(filename, '__file__')] - # Add the names of the .mo files that can be generated - # by compilemessages management command to the list of files watched. - basedirs = [os.path.join(os.path.dirname(os.path.dirname(__file__)), - 'conf', 'locale'), - 'locale'] - basedirs.extend(settings.LOCALE_PATHS) - basedirs = [os.path.abspath(basedir) for basedir in basedirs - if os.path.isdir(basedir)] - for basedir in basedirs: - for dirpath, dirnames, locale_filenames in os.walk(basedir): - for filename in locale_filenames: - if filename.endswith('.mo'): - filenames.append(os.path.join(dirpath, filename)) + if settings.USE_I18N: + # Add the names of the .mo files that can be generated + # by compilemessages management command to the list of files watched. + basedirs = [os.path.join(os.path.dirname(os.path.dirname(__file__)), + 'conf', 'locale'), + 'locale'] + for appname in reversed(settings.INSTALLED_APPS): + app = import_module(appname) + basedirs.append(os.path.join(os.path.dirname(upath(app.__file__)), + 'locale')) + basedirs.extend(settings.LOCALE_PATHS) + basedirs = [os.path.abspath(basedir) for basedir in basedirs + if os.path.isdir(basedir)] + for basedir in basedirs: + for dirpath, dirnames, locale_filenames in os.walk(basedir): + for filename in locale_filenames: + if filename.endswith('.mo'): + filenames.append(os.path.join(dirpath, filename)) for filename in filenames + _error_files: if not filename: diff --git a/tests/utils_tests/test_autoreload.py b/tests/utils_tests/test_autoreload.py index 3843ecafb4..d6e22ad8ee 100644 --- a/tests/utils_tests/test_autoreload.py +++ b/tests/utils_tests/test_autoreload.py @@ -1,6 +1,7 @@ import os from django import conf +from django.contrib import admin from django.test import TestCase, override_settings from django.utils.autoreload import gen_filenames @@ -13,25 +14,53 @@ class TestFilenameGenerator(TestCase): Test that gen_filenames() also yields the built-in django locale files. """ filenames = list(gen_filenames()) - locales = [] + self.assertIn(os.path.join(os.path.dirname(conf.__file__), 'locale', + 'nl', 'LC_MESSAGES', 'django.mo'), + filenames) - basedir = os.path.join(os.path.dirname(conf.__file__), 'locale') - for dirpath, dirnames, locale_filenames in os.walk(basedir): - for filename in locale_filenames: - if filename.endswith('.mo'): - locales.append(os.path.join(dirpath, filename)) - - self.assertTrue(len(locales) > 10) # assume a few available locales - for filename in locales: - self.assertIn(filename, filenames) - - @override_settings( - LOCALE_PATHS=(LOCALE_PATH,) - ) - def test_app_locales(self): + @override_settings(LOCALE_PATHS=(LOCALE_PATH,)) + def test_locale_paths_setting(self): """ - Test that gen_filenames also yields from LOCALE_PATHS. + Test that gen_filenames also yields from LOCALE_PATHS locales. """ filenames = list(gen_filenames()) self.assertIn(os.path.join(LOCALE_PATH, 'nl', 'LC_MESSAGES', 'django.mo'), filenames) + + @override_settings(INSTALLED_APPS=()) + def test_project_root_locale(self): + """ + Test that gen_filenames also yields from the current directory (project + root). + """ + old_cwd = os.getcwd() + os.chdir(os.path.dirname(__file__)) + try: + filenames = list(gen_filenames()) + self.assertIn( + os.path.join(LOCALE_PATH, 'nl', 'LC_MESSAGES', 'django.mo'), + filenames) + finally: + os.chdir(old_cwd) + + @override_settings(INSTALLED_APPS=('django.contrib.admin',)) + def test_app_locales(self): + """ + Test that gen_filenames also yields from INSTALLED_APPS locales. + """ + filenames = list(gen_filenames()) + self.assertIn(os.path.join(os.path.dirname(admin.__file__), 'locale', + 'nl', 'LC_MESSAGES', 'django.mo'), + filenames) + + @override_settings(USE_I18N=False) + def test_no_i18n(self): + """ + If i18n machinery is disabled, there is no need for watching the + locale files. + """ + filenames = list(gen_filenames()) + self.assertNotIn( + os.path.join(os.path.dirname(conf.__file__), 'locale', 'nl', + 'LC_MESSAGES', 'django.mo'), + filenames)