diff options
| author | Jannis Leidel <jannis@leidel.info> | 2012-11-17 15:37:30 +0100 |
|---|---|---|
| committer | Jannis Leidel <jannis@leidel.info> | 2012-11-17 15:39:34 +0100 |
| commit | 0e3f7814d7106768e8eafcba0e74238fcdb90f9d (patch) | |
| tree | 96cbb39e2be88a8cf1745a7bc32ff96b38f67882 | |
| parent | d69c3bf1373b2cb961c445802bc1b5d0d871f887 (diff) | |
[1.5.x] Fixed #19136 -- Properly escape gettext context prefixes in the i18n JavaScript view template.
Backport of 4a5e8087ac7676ef08e76275c1f756778b39c13e from master.
| -rw-r--r-- | django/views/i18n.py | 8 | ||||
| -rw-r--r-- | tests/regressiontests/views/locale/de/LC_MESSAGES/djangojs.mo | bin | 0 -> 615 bytes | |||
| -rw-r--r-- | tests/regressiontests/views/locale/de/LC_MESSAGES/djangojs.po | 40 | ||||
| -rw-r--r-- | tests/regressiontests/views/templates/jsi18n.html | 44 | ||||
| -rw-r--r-- | tests/regressiontests/views/tests/__init__.py | 2 | ||||
| -rw-r--r-- | tests/regressiontests/views/tests/i18n.py | 52 | ||||
| -rw-r--r-- | tests/regressiontests/views/urls.py | 7 | ||||
| -rw-r--r-- | tests/regressiontests/views/views.py | 3 |
8 files changed, 148 insertions, 8 deletions
diff --git a/django/views/i18n.py b/django/views/i18n.py index 00ef224254..96643f0d7d 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -99,16 +99,16 @@ function ngettext(singular, plural, count) { function gettext_noop(msgid) { return msgid; } function pgettext(context, msgid) { - var value = gettext(context + '\x04' + msgid); - if (value.indexOf('\x04') != -1) { + var value = gettext(context + '\\x04' + msgid); + if (value.indexOf('\\x04') != -1) { value = msgid; } return value; } function npgettext(context, singular, plural, count) { - var value = ngettext(context + '\x04' + singular, context + '\x04' + plural, count); - if (value.indexOf('\x04') != -1) { + var value = ngettext(context + '\\x04' + singular, context + '\\x04' + plural, count); + if (value.indexOf('\\x04') != -1) { value = ngettext(singular, plural, count); } return value; diff --git a/tests/regressiontests/views/locale/de/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/locale/de/LC_MESSAGES/djangojs.mo Binary files differnew file mode 100644 index 0000000000..34ba691029 --- /dev/null +++ b/tests/regressiontests/views/locale/de/LC_MESSAGES/djangojs.mo diff --git a/tests/regressiontests/views/locale/de/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/locale/de/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..88cc35e88f --- /dev/null +++ b/tests/regressiontests/views/locale/de/LC_MESSAGES/djangojs.po @@ -0,0 +1,40 @@ +# 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-01-21 21:37-0300\n" +"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" +"Language-Team: de <de@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:7 +msgctxt "month name" +msgid "May" +msgstr "Mai" + +#: models.py:9 +msgctxt "verb" +msgid "May" +msgstr "Kann" + +#: models.py:11 +msgid "%s item" +msgid_plural "%s items" +msgstr[0] "%s Element" +msgstr[1] "%s Elemente" + +#: models.py:11 +msgctxt "search" +msgid "%s result" +msgid_plural "%s results" +msgstr[0] "%s Resultat" +msgstr[1] "%s Resultate" diff --git a/tests/regressiontests/views/templates/jsi18n.html b/tests/regressiontests/views/templates/jsi18n.html new file mode 100644 index 0000000000..d6093c8ef4 --- /dev/null +++ b/tests/regressiontests/views/templates/jsi18n.html @@ -0,0 +1,44 @@ +<html> +<head> + <script type="text/javascript" src="/jsi18n_admin/"></script> +</head> + +<body> + <p id="gettext"> + <script type="text/javascript"> + document.write(gettext("Remove")); + </script> + </p> + + <p id="ngettext_sing"> + <script type="text/javascript"> + document.write(interpolate(ngettext("%s item", "%s items", 1), [1])); + </script> + </p> + + <p id="ngettext_plur"> + <script type="text/javascript"> + document.write(interpolate(ngettext("%s item", "%s items", 455), [455])); + </script> + </p> + + <p id="pgettext"> + <script type="text/javascript"> + document.write(pgettext("verb", "May")); + </script> + </p> + + <p id="npgettext_sing"> + <script type="text/javascript"> + document.write(interpolate(npgettext("search", "%s result", "%s results", 1), [1])); + </script> + </p> + + <p id="npgettext_plur"> + <script type="text/javascript"> + document.write(interpolate(npgettext("search", "%s result", "%s results", 455), [455])); + </script> + </p> + +</body> +</html> diff --git a/tests/regressiontests/views/tests/__init__.py b/tests/regressiontests/views/tests/__init__.py index 12d0c59014..17f3f4562d 100644 --- a/tests/regressiontests/views/tests/__init__.py +++ b/tests/regressiontests/views/tests/__init__.py @@ -4,7 +4,7 @@ from .debug import (DebugViewTests, ExceptionReporterTests, ExceptionReporterTests, PlainTextReportTests, ExceptionReporterFilterTests, AjaxResponseExceptionReporterFilter) from .defaults import DefaultsTests -from .i18n import JsI18NTests, I18NTests, JsI18NTestsMultiPackage +from .i18n import JsI18NTests, I18NTests, JsI18NTestsMultiPackage, JavascriptI18nTests from .shortcuts import ShortcutTests from .specials import URLHandling from .static import StaticHelperTest, StaticUtilsTests, StaticTests diff --git a/tests/regressiontests/views/tests/i18n.py b/tests/regressiontests/views/tests/i18n.py index 601df6d512..d0bf7d2299 100644 --- a/tests/regressiontests/views/tests/i18n.py +++ b/tests/regressiontests/views/tests/i18n.py @@ -6,11 +6,17 @@ from os import path from django.conf import settings from django.core.urlresolvers import reverse -from django.test import TestCase -from django.utils import six -from django.utils.translation import override, get_language +from django.test import LiveServerTestCase, TestCase +from django.test.utils import override_settings +from django.utils import six, unittest +from django.utils.translation import override from django.utils.text import javascript_quote +try: + from selenium.webdriver.firefox import webdriver as firefox +except ImportError: + firefox = None + from ..urls import locale_dir @@ -152,3 +158,43 @@ class JsI18NTestsMultiPackage(TestCase): response = self.client.get('/views/jsi18n/') self.assertContains(response, javascript_quote('este texto de app3 debe ser traducido')) + + +@unittest.skipUnless(firefox, 'Selenium not installed') +class JavascriptI18nTests(LiveServerTestCase): + urls = 'regressiontests.views.urls' + + @classmethod + def setUpClass(cls): + cls.selenium = firefox.WebDriver() + super(JavascriptI18nTests, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + cls.selenium.quit() + super(JavascriptI18nTests, cls).tearDownClass() + + @override_settings(LANGUAGE_CODE='de') + def test_javascript_gettext(self): + extended_apps = list(settings.INSTALLED_APPS) + ['regressiontests.views'] + with self.settings(INSTALLED_APPS=extended_apps): + self.selenium.get('%s%s' % (self.live_server_url, '/jsi18n_template/')) + + elem = self.selenium.find_element_by_id("gettext") + self.assertEqual(elem.text, u"Entfernen") + elem = self.selenium.find_element_by_id("ngettext_sing") + self.assertEqual(elem.text, "1 Element") + elem = self.selenium.find_element_by_id("ngettext_plur") + self.assertEqual(elem.text, "455 Elemente") + elem = self.selenium.find_element_by_id("pgettext") + self.assertEqual(elem.text, "Kann") + elem = self.selenium.find_element_by_id("npgettext_sing") + self.assertEqual(elem.text, "1 Resultat") + elem = self.selenium.find_element_by_id("npgettext_plur") + self.assertEqual(elem.text, "455 Resultate") + + def test_escaping(self): + extended_apps = list(settings.INSTALLED_APPS) + ['regressiontests.views'] + with self.settings(INSTALLED_APPS=extended_apps): + response = self.client.get('%s%s' % (self.live_server_url, '/jsi18n_admin/')) + self.assertContains(response, '\\x04') diff --git a/tests/regressiontests/views/urls.py b/tests/regressiontests/views/urls.py index 90d2382f71..ae3b9c0a9e 100644 --- a/tests/regressiontests/views/urls.py +++ b/tests/regressiontests/views/urls.py @@ -32,6 +32,11 @@ js_info_dict_multi_packages2 = { 'packages': ('regressiontests.views.app3', 'regressiontests.views.app4'), } +js_info_dict_admin = { + 'domain': 'djangojs', + 'packages': ('django.contrib.admin', 'regressiontests.views'), +} + urlpatterns = patterns('', (r'^$', views.index_page), @@ -51,6 +56,8 @@ urlpatterns = patterns('', (r'^jsi18n_english_translation/$', 'django.views.i18n.javascript_catalog', js_info_dict_english_translation), (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), + (r'^jsi18n_admin/$', 'django.views.i18n.javascript_catalog', js_info_dict_admin), + (r'^jsi18n_template/$', views.jsi18n), # Static views (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': media_dir}), diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py index 2836d1bdde..ed9d61144a 100644 --- a/tests/regressiontests/views/views.py +++ b/tests/regressiontests/views/views.py @@ -51,6 +51,9 @@ def template_exception(request, n): return render_to_response('debug/template_exception.html', {'arg': except_args[int(n)]}) +def jsi18n(request): + return render_to_response('jsi18n.html') + # Some views to exercise the shortcuts def render_to_response_view(request): |
