Fixed #19136 -- Properly escape gettext context prefixes in the i18n JavaScript view template.

This commit is contained in:
Jannis Leidel 2012-11-17 15:37:30 +01:00
parent 44046e8a38
commit 4a5e8087ac
8 changed files with 148 additions and 8 deletions

View File

@ -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;

View File

@ -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"

View File

@ -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>

View File

@ -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

View File

@ -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')

View File

@ -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}),

View File

@ -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):