Fixed #19136 -- Properly escape gettext context prefixes in the i18n JavaScript view template.
This commit is contained in:
parent
44046e8a38
commit
4a5e8087ac
|
@ -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;
|
||||
|
|
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,
|
||||
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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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}),
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue