[1.5.x] Fixed #19136 -- Properly escape gettext context prefixes in the i18n JavaScript view template.
Backport of 4a5e8087ac
from master.
This commit is contained in:
parent
d69c3bf137
commit
0e3f7814d7
|
@ -99,16 +99,16 @@ function ngettext(singular, plural, count) {
|
||||||
function gettext_noop(msgid) { return msgid; }
|
function gettext_noop(msgid) { return msgid; }
|
||||||
|
|
||||||
function pgettext(context, msgid) {
|
function pgettext(context, msgid) {
|
||||||
var value = gettext(context + '\x04' + msgid);
|
var value = gettext(context + '\\x04' + msgid);
|
||||||
if (value.indexOf('\x04') != -1) {
|
if (value.indexOf('\\x04') != -1) {
|
||||||
value = msgid;
|
value = msgid;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function npgettext(context, singular, plural, count) {
|
function npgettext(context, singular, plural, count) {
|
||||||
var value = ngettext(context + '\x04' + singular, context + '\x04' + plural, count);
|
var value = ngettext(context + '\\x04' + singular, context + '\\x04' + plural, count);
|
||||||
if (value.indexOf('\x04') != -1) {
|
if (value.indexOf('\\x04') != -1) {
|
||||||
value = ngettext(singular, plural, count);
|
value = ngettext(singular, plural, count);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
|
Binary file not shown.
|
@ -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"
|
|
@ -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>
|
|
@ -4,7 +4,7 @@ from .debug import (DebugViewTests, ExceptionReporterTests,
|
||||||
ExceptionReporterTests, PlainTextReportTests, ExceptionReporterFilterTests,
|
ExceptionReporterTests, PlainTextReportTests, ExceptionReporterFilterTests,
|
||||||
AjaxResponseExceptionReporterFilter)
|
AjaxResponseExceptionReporterFilter)
|
||||||
from .defaults import DefaultsTests
|
from .defaults import DefaultsTests
|
||||||
from .i18n import JsI18NTests, I18NTests, JsI18NTestsMultiPackage
|
from .i18n import JsI18NTests, I18NTests, JsI18NTestsMultiPackage, JavascriptI18nTests
|
||||||
from .shortcuts import ShortcutTests
|
from .shortcuts import ShortcutTests
|
||||||
from .specials import URLHandling
|
from .specials import URLHandling
|
||||||
from .static import StaticHelperTest, StaticUtilsTests, StaticTests
|
from .static import StaticHelperTest, StaticUtilsTests, StaticTests
|
||||||
|
|
|
@ -6,11 +6,17 @@ from os import path
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.test import TestCase
|
from django.test import LiveServerTestCase, TestCase
|
||||||
from django.utils import six
|
from django.test.utils import override_settings
|
||||||
from django.utils.translation import override, get_language
|
from django.utils import six, unittest
|
||||||
|
from django.utils.translation import override
|
||||||
from django.utils.text import javascript_quote
|
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
|
from ..urls import locale_dir
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,3 +158,43 @@ class JsI18NTestsMultiPackage(TestCase):
|
||||||
response = self.client.get('/views/jsi18n/')
|
response = self.client.get('/views/jsi18n/')
|
||||||
self.assertContains(response,
|
self.assertContains(response,
|
||||||
javascript_quote('este texto de app3 debe ser traducido'))
|
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')
|
||||||
|
|
|
@ -32,6 +32,11 @@ js_info_dict_multi_packages2 = {
|
||||||
'packages': ('regressiontests.views.app3', 'regressiontests.views.app4'),
|
'packages': ('regressiontests.views.app3', 'regressiontests.views.app4'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
js_info_dict_admin = {
|
||||||
|
'domain': 'djangojs',
|
||||||
|
'packages': ('django.contrib.admin', 'regressiontests.views'),
|
||||||
|
}
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
(r'^$', views.index_page),
|
(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_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_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_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
|
# Static views
|
||||||
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': media_dir}),
|
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': media_dir}),
|
||||||
|
|
|
@ -51,6 +51,9 @@ def template_exception(request, n):
|
||||||
return render_to_response('debug/template_exception.html',
|
return render_to_response('debug/template_exception.html',
|
||||||
{'arg': except_args[int(n)]})
|
{'arg': except_args[int(n)]})
|
||||||
|
|
||||||
|
def jsi18n(request):
|
||||||
|
return render_to_response('jsi18n.html')
|
||||||
|
|
||||||
# Some views to exercise the shortcuts
|
# Some views to exercise the shortcuts
|
||||||
|
|
||||||
def render_to_response_view(request):
|
def render_to_response_view(request):
|
||||||
|
|
Loading…
Reference in New Issue