diff --git a/django/views/i18n.py b/django/views/i18n.py index 831a764a2a..2078649e3d 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -213,13 +213,16 @@ def javascript_catalog(request, domain='djangojs', packages=None): if en_catalog_missing: t = {} else: + locale_t = {} for path in paths: try: catalog = gettext_module.translation(domain, path, [locale]) except IOError: catalog = None if catalog is not None: - t = catalog._catalog + locale_t.update(catalog._catalog) + if locale_t: + t = locale_t src = [LibHead] plural = None if '' in t: diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index a516cf1b64..1385e5e0aa 100644 --- a/tests/regressiontests/admin_views/tests.py +++ b/tests/regressiontests/admin_views/tests.py @@ -4,7 +4,6 @@ import re import datetime from django.conf import settings from django.core.files import temp as tempfile -from django.test import TestCase from django.contrib.auth import admin # Register auth models with the admin. from django.contrib.auth.models import User, Permission, UNUSABLE_PASSWORD from django.contrib.contenttypes.models import ContentType @@ -13,15 +12,16 @@ from django.contrib.admin.sites import LOGIN_FORM_KEY from django.contrib.admin.util import quote from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME from django.forms.util import ErrorList +from django.test import TestCase from django.utils import formats from django.utils.cache import get_max_age +from django.utils.encoding import iri_to_uri from django.utils.html import escape from django.utils.translation import get_date_formats, activate, deactivate -from django.utils.encoding import iri_to_uri # local test models from models import Article, BarAccount, CustomArticle, EmptyModel, \ - ExternalSubscriber, FooAccount, Gallery, ModelWithStringPrimaryKey, \ + FooAccount, Gallery, ModelWithStringPrimaryKey, \ Person, Persona, Picture, Podcast, Section, Subscriber, Vodcast, \ Language, Collector, Widget, Grommet, DooHickey, FancyDoodad, Whatsit, \ Category, Post, Plot, FunkyTag @@ -36,9 +36,11 @@ class AdminViewBasicTest(TestCase): urlbit = 'admin' def setUp(self): + self.old_language_code = settings.LANGUAGE_CODE self.client.login(username='super', password='secret') def tearDown(self): + settings.LANGUAGE_CODE = self.old_language_code self.client.logout() def testTrailingSlashRequired(self): @@ -278,26 +280,22 @@ class AdminViewBasicTest(TestCase): if the default language is non-English but the selected language is English. See #13388 and #3594 for more details. """ - old_language_code = settings.LANGUAGE_CODE settings.LANGUAGE_CODE = 'fr' activate('en-us') response = self.client.get('/test_admin/admin/jsi18n/') self.assertNotContains(response, 'Choisir une heure') deactivate() - settings.LANGUAGE_CODE = old_language_code def testI18NLanguageNonEnglishFallback(self): """ Makes sure that the fallback language is still working properly in cases where the selected language cannot be found. """ - old_language_code = settings.LANGUAGE_CODE settings.LANGUAGE_CODE = 'fr' activate('none') response = self.client.get('/test_admin/admin/jsi18n/') self.assertContains(response, 'Choisir une heure') deactivate() - settings.LANGUAGE_CODE = old_language_code class SaveAsTests(TestCase): diff --git a/tests/regressiontests/views/app1/__init__.py b/tests/regressiontests/views/app1/__init__.py new file mode 100644 index 0000000000..792d600548 --- /dev/null +++ b/tests/regressiontests/views/app1/__init__.py @@ -0,0 +1 @@ +# diff --git a/tests/regressiontests/views/app1/locale/fr/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/app1/locale/fr/LC_MESSAGES/djangojs.mo new file mode 100644 index 0000000000..5d6aecb446 Binary files /dev/null and b/tests/regressiontests/views/app1/locale/fr/LC_MESSAGES/djangojs.mo differ diff --git a/tests/regressiontests/views/app1/locale/fr/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/app1/locale/fr/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..a4627db877 --- /dev/null +++ b/tests/regressiontests/views/app1/locale/fr/LC_MESSAGES/djangojs.po @@ -0,0 +1,20 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-09-15 19:15+0200\n" +"PO-Revision-Date: 2010-05-12 12:41-0300\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "this app1 string is to be translated" +msgstr "il faut traduire cette chaîne de caractères de app1" diff --git a/tests/regressiontests/views/app2/__init__.py b/tests/regressiontests/views/app2/__init__.py new file mode 100644 index 0000000000..792d600548 --- /dev/null +++ b/tests/regressiontests/views/app2/__init__.py @@ -0,0 +1 @@ +# diff --git a/tests/regressiontests/views/app2/locale/fr/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/app2/locale/fr/LC_MESSAGES/djangojs.mo new file mode 100644 index 0000000000..17e1863672 Binary files /dev/null and b/tests/regressiontests/views/app2/locale/fr/LC_MESSAGES/djangojs.mo differ diff --git a/tests/regressiontests/views/app2/locale/fr/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/app2/locale/fr/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..637b9e6bcd --- /dev/null +++ b/tests/regressiontests/views/app2/locale/fr/LC_MESSAGES/djangojs.po @@ -0,0 +1,20 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-09-15 19:15+0200\n" +"PO-Revision-Date: 2010-05-12 22:05-0300\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "this app2 string is to be translated" +msgstr "il faut traduire cette chaîne de caractères de app2" diff --git a/tests/regressiontests/views/app3/__init__.py b/tests/regressiontests/views/app3/__init__.py new file mode 100644 index 0000000000..792d600548 --- /dev/null +++ b/tests/regressiontests/views/app3/__init__.py @@ -0,0 +1 @@ +# diff --git a/tests/regressiontests/views/app3/locale/es_AR/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/app3/locale/es_AR/LC_MESSAGES/djangojs.mo new file mode 100644 index 0000000000..0c485a9838 Binary files /dev/null and b/tests/regressiontests/views/app3/locale/es_AR/LC_MESSAGES/djangojs.mo differ diff --git a/tests/regressiontests/views/app3/locale/es_AR/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/app3/locale/es_AR/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..1e3be0bfea --- /dev/null +++ b/tests/regressiontests/views/app3/locale/es_AR/LC_MESSAGES/djangojs.po @@ -0,0 +1,20 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-09-15 19:15+0200\n" +"PO-Revision-Date: 2010-05-12 12:41-0300\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "il faut traduire cette chaîne de caractères de app3" +msgstr "este texto de app3 debe ser traducido" diff --git a/tests/regressiontests/views/app4/__init__.py b/tests/regressiontests/views/app4/__init__.py new file mode 100644 index 0000000000..792d600548 --- /dev/null +++ b/tests/regressiontests/views/app4/__init__.py @@ -0,0 +1 @@ +# diff --git a/tests/regressiontests/views/app4/locale/es_AR/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/app4/locale/es_AR/LC_MESSAGES/djangojs.mo new file mode 100644 index 0000000000..581fbb0347 Binary files /dev/null and b/tests/regressiontests/views/app4/locale/es_AR/LC_MESSAGES/djangojs.mo differ diff --git a/tests/regressiontests/views/app4/locale/es_AR/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/app4/locale/es_AR/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..27403c0783 --- /dev/null +++ b/tests/regressiontests/views/app4/locale/es_AR/LC_MESSAGES/djangojs.po @@ -0,0 +1,20 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-09-15 19:15+0200\n" +"PO-Revision-Date: 2010-05-12 12:41-0300\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "il faut traduire cette chaîne de caractères de app4" +msgstr "este texto de app4 debe ser traducido" diff --git a/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.mo index 01c002e9e0..b6b088752a 100644 Binary files a/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.mo and b/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.mo differ diff --git a/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.po index 03c01b7656..669af4bf19 100644 --- a/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.po +++ b/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.po @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-09-15 16:45+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: 2010-05-12 12:57-0300\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" @@ -18,4 +18,8 @@ msgstr "" #: media/js/translate.js:1 msgid "this is to be translated" -msgstr "esto tiene que ser traducido" \ No newline at end of file +msgstr "esto tiene que ser traducido" + + +msgid "Choose a time" +msgstr "Elige una hora" diff --git a/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.mo index 4feca0b44d..356147cf11 100644 Binary files a/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.mo and b/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.mo differ diff --git a/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.po index 9cfaa23232..0d03f95845 100644 --- a/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.po +++ b/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.po @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-09-15 19:15+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: 2010-05-12 12:41-0300\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" @@ -17,4 +17,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" msgid "this is to be translated" -msgstr "il faut le traduire" \ No newline at end of file +msgstr "il faut le traduire" + + +msgid "Choose a time" +msgstr "Choisir une heure" diff --git a/tests/regressiontests/views/locale/ru/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/locale/ru/LC_MESSAGES/djangojs.mo index 148cba533b..21659a93d3 100644 Binary files a/tests/regressiontests/views/locale/ru/LC_MESSAGES/djangojs.mo and b/tests/regressiontests/views/locale/ru/LC_MESSAGES/djangojs.mo differ diff --git a/tests/regressiontests/views/locale/ru/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/locale/ru/LC_MESSAGES/djangojs.po index a0ff0152ed..4ea193a880 100644 --- a/tests/regressiontests/views/locale/ru/LC_MESSAGES/djangojs.po +++ b/tests/regressiontests/views/locale/ru/LC_MESSAGES/djangojs.po @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-09-15 16:45+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: 2010-05-12 12:57-0300\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" @@ -17,4 +17,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" msgid "this is to be translated" -msgstr "перевод" \ No newline at end of file +msgstr "перевод" + + +msgid "Choose a time" +msgstr "Выберите время" diff --git a/tests/regressiontests/views/tests/i18n.py b/tests/regressiontests/views/tests/i18n.py index 7debb213f6..9a34738411 100644 --- a/tests/regressiontests/views/tests/i18n.py +++ b/tests/regressiontests/views/tests/i18n.py @@ -1,8 +1,9 @@ +# -*- coding:utf-8 -*- import gettext from django.conf import settings from django.test import TestCase -from django.utils.translation import activate +from django.utils.translation import activate, deactivate from django.utils.text import javascript_quote from regressiontests.views.urls import locale_dir @@ -30,6 +31,7 @@ class I18NTests(TestCase): # javascript_quote is used to be able to check unicode strings self.assertContains(response, javascript_quote(trans_txt), 1) + class JsI18NTests(TestCase): """ Tests django views in django/views/i18n.py that need to change @@ -66,3 +68,68 @@ class JsI18NTests(TestCase): activate('fi') response = self.client.get('/views/jsi18n/') self.assertContains(response, 'il faut le traduire') + + def testI18NLanguageNonEnglishDefault(self): + """ + Check if the Javascript i18n view returns an empty language catalog + 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('/views/jsi18n/') + self.assertNotContains(response, 'Choisir une heure') + 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('/views/jsi18n/') + self.assertContains(response, 'Choisir une heure') + deactivate() + + +class JsI18NTestsMultiPackage(TestCase): + """ + Tests for django views in django/views/i18n.py that need to change + settings.LANGUAGE_CODE and merge JS translation from several packages. + """ + + def setUp(self): + self.old_language_code = settings.LANGUAGE_CODE + self.old_installed_apps = settings.INSTALLED_APPS + + def tearDown(self): + settings.LANGUAGE_CODE = self.old_language_code + settings.INSTALLED_APPS = self.old_installed_apps + + def testI18NLanguageEnglishDefault(self): + """ + Check if the JavaScript i18n view returns a complete language catalog + if the default language is en-us, the selected language has a + translation available and a catalog composed by djangojs domain + translations of multiple Python packages is requested. See #13388, + #3594 and #13514 for more details. + """ + settings.LANGUAGE_CODE = 'en-us' + settings.INSTALLED_APPS = list(settings.INSTALLED_APPS) + ['regressiontests.views.app1', 'regressiontests.views.app2'] + activate('fr') + response = self.client.get('/views/jsi18n_multi_packages1/') + self.assertContains(response, javascript_quote('il faut traduire cette chaîne de caractères de app1')) + deactivate() + + def testI18NDifferentNonEnLangs(self): + """ + Similar to above but with neither default or requested language being + English. + """ + settings.LANGUAGE_CODE = 'fr' + settings.INSTALLED_APPS = list(settings.INSTALLED_APPS) + ['regressiontests.views.app3', 'regressiontests.views.app4'] + activate('es-ar') + response = self.client.get('/views/jsi18n_multi_packages2/') + self.assertContains(response, javascript_quote('este texto de app3 debe ser traducido')) + deactivate() diff --git a/tests/regressiontests/views/urls.py b/tests/regressiontests/views/urls.py index a072e77131..f5675d0e28 100644 --- a/tests/regressiontests/views/urls.py +++ b/tests/regressiontests/views/urls.py @@ -16,6 +16,16 @@ js_info_dict = { 'packages': ('regressiontests.views',), } +js_info_dict_multi_packages1 = { + 'domain': 'djangojs', + 'packages': ('regressiontests.views.app1', 'regressiontests.views.app2'), +} + +js_info_dict_multi_packages2 = { + 'domain': 'djangojs', + 'packages': ('regressiontests.views.app3', 'regressiontests.views.app4'), +} + date_based_info_dict = { 'queryset': Article.objects.all(), 'date_field': 'date_created', @@ -36,6 +46,8 @@ urlpatterns = patterns('', # i18n views (r'^i18n/', include('django.conf.urls.i18n')), (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), + (r'^jsi18n_multi_packages1/$', 'django.views.i18n.javascript_catalog', js_info_dict_multi_packages1), + (r'^jsi18n_multi_packages2/$', 'django.views.i18n.javascript_catalog', js_info_dict_multi_packages2), # Static views (r'^site_media/(?P.*)$', 'django.views.static.serve', {'document_root': media_dir}),