Fixed #22106 -- Allowed using more than one instance of javascript_catalog per project.
This commit is contained in:
parent
556eb67701
commit
6bb2175ed6
|
@ -94,87 +94,87 @@ js_catalog_template = r"""
|
||||||
django.pluralidx = function (count) { return (count == 1) ? 0 : 1; };
|
django.pluralidx = function (count) { return (count == 1) ? 0 : 1; };
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if catalog_str %}
|
|
||||||
/* gettext library */
|
/* gettext library */
|
||||||
|
|
||||||
django.catalog = {{ catalog_str }};
|
django.catalog = django.catalog || {};
|
||||||
|
{% if catalog_str %}
|
||||||
django.gettext = function (msgid) {
|
var newcatalog = {{ catalog_str }};
|
||||||
var value = django.catalog[msgid];
|
for (var key in newcatalog) {
|
||||||
if (typeof(value) == 'undefined') {
|
django.catalog[key] = newcatalog[key];
|
||||||
return msgid;
|
}
|
||||||
} else {
|
|
||||||
return (typeof(value) == 'string') ? value : value[0];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
django.ngettext = function (singular, plural, count) {
|
|
||||||
var value = django.catalog[singular];
|
|
||||||
if (typeof(value) == 'undefined') {
|
|
||||||
return (count == 1) ? singular : plural;
|
|
||||||
} else {
|
|
||||||
return value[django.pluralidx(count)];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
django.gettext_noop = function (msgid) { return msgid; };
|
|
||||||
|
|
||||||
django.pgettext = function (context, msgid) {
|
|
||||||
var value = django.gettext(context + '\x04' + msgid);
|
|
||||||
if (value.indexOf('\x04') != -1) {
|
|
||||||
value = msgid;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
django.npgettext = function (context, singular, plural, count) {
|
|
||||||
var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count);
|
|
||||||
if (value.indexOf('\x04') != -1) {
|
|
||||||
value = django.ngettext(singular, plural, count);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
{% else %}
|
|
||||||
/* gettext identity library */
|
|
||||||
|
|
||||||
django.gettext = function (msgid) { return msgid; };
|
|
||||||
django.ngettext = function (singular, plural, count) { return (count == 1) ? singular : plural; };
|
|
||||||
django.gettext_noop = function (msgid) { return msgid; };
|
|
||||||
django.pgettext = function (context, msgid) { return msgid; };
|
|
||||||
django.npgettext = function (context, singular, plural, count) { return (count == 1) ? singular : plural; };
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
django.interpolate = function (fmt, obj, named) {
|
if (!django.jsi18n_initialized) {
|
||||||
if (named) {
|
django.gettext = function (msgid) {
|
||||||
return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])});
|
var value = django.catalog[msgid];
|
||||||
} else {
|
if (typeof(value) == 'undefined') {
|
||||||
return fmt.replace(/%s/g, function(match){return String(obj.shift())});
|
return msgid;
|
||||||
}
|
} else {
|
||||||
};
|
return (typeof(value) == 'string') ? value : value[0];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
django.ngettext = function (singular, plural, count) {
|
||||||
|
var value = django.catalog[singular];
|
||||||
|
if (typeof(value) == 'undefined') {
|
||||||
|
return (count == 1) ? singular : plural;
|
||||||
|
} else {
|
||||||
|
return value[django.pluralidx(count)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* formatting library */
|
django.gettext_noop = function (msgid) { return msgid; };
|
||||||
|
|
||||||
django.formats = {{ formats_str }};
|
django.pgettext = function (context, msgid) {
|
||||||
|
var value = django.gettext(context + '\x04' + msgid);
|
||||||
django.get_format = function (format_type) {
|
if (value.indexOf('\x04') != -1) {
|
||||||
var value = django.formats[format_type];
|
value = msgid;
|
||||||
if (typeof(value) == 'undefined') {
|
}
|
||||||
return format_type;
|
|
||||||
} else {
|
|
||||||
return value;
|
return value;
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
/* add to global namespace */
|
django.npgettext = function (context, singular, plural, count) {
|
||||||
globals.pluralidx = django.pluralidx;
|
var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count);
|
||||||
globals.gettext = django.gettext;
|
if (value.indexOf('\x04') != -1) {
|
||||||
globals.ngettext = django.ngettext;
|
value = django.ngettext(singular, plural, count);
|
||||||
globals.gettext_noop = django.gettext_noop;
|
}
|
||||||
globals.pgettext = django.pgettext;
|
return value;
|
||||||
globals.npgettext = django.npgettext;
|
};
|
||||||
globals.interpolate = django.interpolate;
|
|
||||||
globals.get_format = django.get_format;
|
django.interpolate = function (fmt, obj, named) {
|
||||||
|
if (named) {
|
||||||
|
return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])});
|
||||||
|
} else {
|
||||||
|
return fmt.replace(/%s/g, function(match){return String(obj.shift())});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* formatting library */
|
||||||
|
|
||||||
|
django.formats = {{ formats_str }};
|
||||||
|
|
||||||
|
django.get_format = function (format_type) {
|
||||||
|
var value = django.formats[format_type];
|
||||||
|
if (typeof(value) == 'undefined') {
|
||||||
|
return format_type;
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* add to global namespace */
|
||||||
|
globals.pluralidx = django.pluralidx;
|
||||||
|
globals.gettext = django.gettext;
|
||||||
|
globals.ngettext = django.ngettext;
|
||||||
|
globals.gettext_noop = django.gettext_noop;
|
||||||
|
globals.pgettext = django.pgettext;
|
||||||
|
globals.npgettext = django.npgettext;
|
||||||
|
globals.interpolate = django.interpolate;
|
||||||
|
globals.get_format = django.get_format;
|
||||||
|
|
||||||
|
django.jsi18n_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
}(this));
|
}(this));
|
||||||
{% endautoescape %}
|
{% endautoescape %}
|
||||||
|
|
|
@ -143,6 +143,9 @@ Internationalization
|
||||||
* The :func:`django.views.i18n.set_language` view now properly redirects to
|
* The :func:`django.views.i18n.set_language` view now properly redirects to
|
||||||
:ref:`translated URLs <url-internationalization>`, when available.
|
:ref:`translated URLs <url-internationalization>`, when available.
|
||||||
|
|
||||||
|
* The :func:`django.views.i18n.javascript_catalog` view now works correctly
|
||||||
|
if used multiple times with different configurations on the same page.
|
||||||
|
|
||||||
Management Commands
|
Management Commands
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -952,6 +952,31 @@ different apps and this changes often and you don't want to pull in one big
|
||||||
catalog file. As a security measure, these values can only be either
|
catalog file. As a security measure, these values can only be either
|
||||||
``django.conf`` or any package from the :setting:`INSTALLED_APPS` setting.
|
``django.conf`` or any package from the :setting:`INSTALLED_APPS` setting.
|
||||||
|
|
||||||
|
You can also split the catalogs in multiple URLs and load them as you need in
|
||||||
|
your sites::
|
||||||
|
|
||||||
|
js_info_dict_app = {
|
||||||
|
'packages': ('your.app.package',),
|
||||||
|
}
|
||||||
|
|
||||||
|
js_info_dict_other_app = {
|
||||||
|
'packages': ('your.other.app.package',),
|
||||||
|
}
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^jsi18n/app/$', javascript_catalog, js_info_dict_app),
|
||||||
|
url(r'^jsi18n/other_app/$', javascript_catalog, js_info_dict_other_app),
|
||||||
|
]
|
||||||
|
|
||||||
|
If you use more than one ``javascript_catalog`` on a site and some of them
|
||||||
|
define the same strings, the strings in the catalog that was loaded last take
|
||||||
|
precedence.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.9
|
||||||
|
|
||||||
|
Before Django 1.9, the catalogs completely overwrote each other and you
|
||||||
|
could only use one at a time.
|
||||||
|
|
||||||
The JavaScript translations found in the paths listed in the
|
The JavaScript translations found in the paths listed in the
|
||||||
:setting:`LOCALE_PATHS` setting are also always included. To keep consistency
|
:setting:`LOCALE_PATHS` setting are also always included. To keep consistency
|
||||||
with the translations lookup order algorithm used for Python and templates, the
|
with the translations lookup order algorithm used for Python and templates, the
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="text/javascript" src="/jsi18n/app1/"></script>
|
||||||
|
<script type="text/javascript" src="/jsi18n/app2/"></script>
|
||||||
|
<body>
|
||||||
|
<p id="app1string">
|
||||||
|
<script type="text/javascript">
|
||||||
|
document.write(gettext('this app1 string is to be translated'))
|
||||||
|
</script>
|
||||||
|
</p>
|
||||||
|
<p id="app2string">
|
||||||
|
<script type="text/javascript">
|
||||||
|
document.write(gettext('this app2 string is to be translated'))
|
||||||
|
</script>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,4 +1,6 @@
|
||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import gettext
|
import gettext
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
@ -100,7 +102,7 @@ class I18NTests(TestCase):
|
||||||
self.assertContains(response, json.dumps(trans_txt), 1)
|
self.assertContains(response, json.dumps(trans_txt), 1)
|
||||||
if lang_code == 'fr':
|
if lang_code == 'fr':
|
||||||
# Message with context (msgctxt)
|
# Message with context (msgctxt)
|
||||||
self.assertContains(response, r'"month name\u0004May": "mai"', 1)
|
self.assertContains(response, '"month name\\u0004May": "mai"', 1)
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ROOT_URLCONF='view_tests.urls')
|
@override_settings(ROOT_URLCONF='view_tests.urls')
|
||||||
|
@ -270,6 +272,16 @@ class JavascriptI18nTests(LiveServerTestCase):
|
||||||
elem = self.selenium.find_element_by_id("npgettext_plur")
|
elem = self.selenium.find_element_by_id("npgettext_plur")
|
||||||
self.assertEqual(elem.text, "455 Resultate")
|
self.assertEqual(elem.text, "455 Resultate")
|
||||||
|
|
||||||
|
@modify_settings(INSTALLED_APPS={'append': ['view_tests.app1', 'view_tests.app2']})
|
||||||
|
@override_settings(LANGUAGE_CODE='fr')
|
||||||
|
def test_multiple_catalogs(self):
|
||||||
|
self.selenium.get('%s%s' % (self.live_server_url, '/jsi18n_multi_catalogs/'))
|
||||||
|
|
||||||
|
elem = self.selenium.find_element_by_id('app1string')
|
||||||
|
self.assertEqual(elem.text, 'il faut traduire cette chaîne de caractères de app1')
|
||||||
|
elem = self.selenium.find_element_by_id('app2string')
|
||||||
|
self.assertEqual(elem.text, 'il faut traduire cette chaîne de caractères de app2')
|
||||||
|
|
||||||
|
|
||||||
class JavascriptI18nChromeTests(JavascriptI18nTests):
|
class JavascriptI18nChromeTests(JavascriptI18nTests):
|
||||||
webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver'
|
webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver'
|
||||||
|
|
|
@ -38,6 +38,16 @@ js_info_dict_admin = {
|
||||||
'packages': ('django.contrib.admin', 'view_tests'),
|
'packages': ('django.contrib.admin', 'view_tests'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
js_info_dict_app1 = {
|
||||||
|
'domain': 'djangojs',
|
||||||
|
'packages': ('view_tests.app1',),
|
||||||
|
}
|
||||||
|
|
||||||
|
js_info_dict_app2 = {
|
||||||
|
'domain': 'djangojs',
|
||||||
|
'packages': ('view_tests.app2',),
|
||||||
|
}
|
||||||
|
|
||||||
js_info_dict_app5 = {
|
js_info_dict_app5 = {
|
||||||
'domain': 'djangojs',
|
'domain': 'djangojs',
|
||||||
'packages': ('view_tests.app5',),
|
'packages': ('view_tests.app5',),
|
||||||
|
@ -64,12 +74,15 @@ urlpatterns = [
|
||||||
# i18n views
|
# i18n views
|
||||||
url(r'^i18n/', include('django.conf.urls.i18n')),
|
url(r'^i18n/', include('django.conf.urls.i18n')),
|
||||||
url(r'^jsi18n/$', i18n.javascript_catalog, js_info_dict),
|
url(r'^jsi18n/$', i18n.javascript_catalog, js_info_dict),
|
||||||
|
url(r'^jsi18n/app1/$', i18n.javascript_catalog, js_info_dict_app1),
|
||||||
|
url(r'^jsi18n/app2/$', i18n.javascript_catalog, js_info_dict_app2),
|
||||||
url(r'^jsi18n/app5/$', i18n.javascript_catalog, js_info_dict_app5),
|
url(r'^jsi18n/app5/$', i18n.javascript_catalog, js_info_dict_app5),
|
||||||
url(r'^jsi18n_english_translation/$', i18n.javascript_catalog, js_info_dict_english_translation),
|
url(r'^jsi18n_english_translation/$', i18n.javascript_catalog, js_info_dict_english_translation),
|
||||||
url(r'^jsi18n_multi_packages1/$', i18n.javascript_catalog, js_info_dict_multi_packages1),
|
url(r'^jsi18n_multi_packages1/$', i18n.javascript_catalog, js_info_dict_multi_packages1),
|
||||||
url(r'^jsi18n_multi_packages2/$', i18n.javascript_catalog, js_info_dict_multi_packages2),
|
url(r'^jsi18n_multi_packages2/$', i18n.javascript_catalog, js_info_dict_multi_packages2),
|
||||||
url(r'^jsi18n_admin/$', i18n.javascript_catalog, js_info_dict_admin),
|
url(r'^jsi18n_admin/$', i18n.javascript_catalog, js_info_dict_admin),
|
||||||
url(r'^jsi18n_template/$', views.jsi18n),
|
url(r'^jsi18n_template/$', views.jsi18n),
|
||||||
|
url(r'^jsi18n_multi_catalogs/$', views.jsi18n_multi_catalogs),
|
||||||
|
|
||||||
# Static views
|
# Static views
|
||||||
url(r'^site_media/(?P<path>.*)$', static.serve, {'document_root': media_dir}),
|
url(r'^site_media/(?P<path>.*)$', static.serve, {'document_root': media_dir}),
|
||||||
|
|
|
@ -82,6 +82,10 @@ def jsi18n(request):
|
||||||
return render_to_response('jsi18n.html')
|
return render_to_response('jsi18n.html')
|
||||||
|
|
||||||
|
|
||||||
|
def jsi18n_multi_catalogs(request):
|
||||||
|
return render_to_response('jsi18n-multi-catalogs.html')
|
||||||
|
|
||||||
|
|
||||||
def raises_template_does_not_exist(request, path='i_dont_exist.html'):
|
def raises_template_does_not_exist(request, path='i_dont_exist.html'):
|
||||||
# We need to inspect the HTML generated by the fancy 500 debug view but
|
# We need to inspect the HTML generated by the fancy 500 debug view but
|
||||||
# the test client ignores it, so we send it explicitly.
|
# the test client ignores it, so we send it explicitly.
|
||||||
|
|
Loading…
Reference in New Issue