diff --git a/django/utils/formats.py b/django/utils/formats.py index 3c43f52f2f1..0dc23402f20 100644 --- a/django/utils/formats.py +++ b/django/utils/formats.py @@ -14,11 +14,21 @@ from django.utils.safestring import mark_safe _format_cache = {} _format_modules_cache = {} +def reset_format_cache(): + """Clear any cached formats. + + This method is provided primarily for testing purposes, + so that the effects of cached formats can be removed. + """ + global _format_cache, _format_modules_cache + _format_cache = {} + _format_modules_cache = {} + def iter_format_modules(lang): """ Does the heavy lifting of finding format modules. """ - if check_for_language(lang) or settings.USE_L10N: + if check_for_language(lang): format_locations = ['django.conf.locale.%s'] if settings.FORMAT_MODULE_PATH: format_locations.append(settings.FORMAT_MODULE_PATH + '.%s') diff --git a/django/views/i18n.py b/django/views/i18n.py index bfb4bfaca12..096fdeafb3e 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -7,7 +7,7 @@ from django.utils import importlib from django.utils.translation import check_for_language, activate, to_locale, get_language from django.utils.text import javascript_quote from django.utils.encoding import smart_unicode -from django.utils.formats import get_format_modules +from django.utils.formats import get_format_modules, get_format def set_language(request): """ @@ -49,10 +49,7 @@ def get_formats(): result = {} for module in [settings] + get_format_modules(reverse=True): for attr in FORMAT_SETTINGS: - try: - result[attr] = getattr(module, attr) - except AttributeError: - pass + result[attr] = get_format(attr) src = [] for k, v in result.items(): if isinstance(v, (basestring, int)): diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index 54cc7493026..21c5eb3471c 100644 --- a/tests/regressiontests/admin_views/tests.py +++ b/tests/regressiontests/admin_views/tests.py @@ -48,12 +48,18 @@ class AdminViewBasicTest(TestCase): urlbit = 'admin' def setUp(self): - self.old_language_code = settings.LANGUAGE_CODE + self.old_USE_I18N = settings.LANGUAGE_CODE + self.old_USE_L10N = settings.USE_L10N + self.old_LANGUAGE_CODE = settings.LANGUAGE_CODE self.client.login(username='super', password='secret') + settings.USE_I18N = True def tearDown(self): - settings.LANGUAGE_CODE = self.old_language_code + settings.USE_I18N = self.old_USE_I18N + settings.USE_L10N = self.old_USE_L10N + settings.LANGUAGE_CODE = self.old_LANGUAGE_CODE self.client.logout() + formats.reset_format_cache() def testTrailingSlashRequired(self): """ @@ -351,22 +357,42 @@ class AdminViewBasicTest(TestCase): if the default language is non-English but the selected language is English. See #13388 and #3594 for more details. """ - settings.LANGUAGE_CODE = 'fr' - activate('en-us') - response = self.client.get('/test_admin/admin/jsi18n/') - self.assertNotContains(response, 'Choisir une heure') - deactivate() + try: + settings.LANGUAGE_CODE = 'fr' + activate('en-us') + response = self.client.get('/test_admin/admin/jsi18n/') + self.assertNotContains(response, 'Choisir une heure') + finally: + deactivate() def testI18NLanguageNonEnglishFallback(self): """ Makes sure that the fallback language is still working properly in cases where the selected language cannot be found. """ - settings.LANGUAGE_CODE = 'fr' - activate('none') - response = self.client.get('/test_admin/admin/jsi18n/') - self.assertContains(response, 'Choisir une heure') - deactivate() + try: + settings.LANGUAGE_CODE = 'fr' + activate('none') + response = self.client.get('/test_admin/admin/jsi18n/') + self.assertContains(response, 'Choisir une heure') + finally: + deactivate() + + def testL10NDeactivated(self): + """ + Check if L10N is deactivated, the Javascript i18n view doesn't + return localized date/time formats. Refs #14824. + """ + try: + settings.LANGUAGE_CODE = 'ru' + settings.USE_L10N = False + activate('ru') + response = self.client.get('/test_admin/admin/jsi18n/') + self.assertNotContains(response, '%d.%m.%Y %H:%M:%S') + self.assertContains(response, '%Y-%m-%d %H:%M:%S') + finally: + deactivate() + def test_disallowed_filtering(self): self.assertRaises(SuspiciousOperation,