From 49dd45138efcd223578b06657d524c238ab940a4 Mon Sep 17 00:00:00 2001 From: dzhuang Date: Mon, 12 Mar 2018 18:00:35 +0800 Subject: [PATCH] Optimized js i18n of DataTable and FullCalendar. --- course/templates/course/calendar.html | 4 +- course/templates/course/gradebook-by-opp.html | 2 +- .../templates/course/gradebook-opp-list.html | 2 +- .../course/gradebook-participant.html | 2 +- course/templates/course/gradebook.html | 2 +- .../templates/course/participation-table.html | 2 +- course/templatetags/coursetags.py | 34 ++++++++--- package.json | 2 +- relate/utils.py | 24 -------- requirements.txt | 3 - setup.py | 1 - tests/test_misc.py | 59 ++++++++++++++++++- 12 files changed, 93 insertions(+), 44 deletions(-) diff --git a/course/templates/course/calendar.html b/course/templates/course/calendar.html index 2fcc66e85..f309c91d9 100644 --- a/course/templates/course/calendar.html +++ b/course/templates/course/calendar.html @@ -14,7 +14,9 @@ {# load calendar with local language #} {% get_current_language as LANGUAGE_CODE %} - + {% if LANGUAGE_CODE != "en" %} + + {% endif %} {% endblock %} {% block content %} diff --git a/course/templates/course/gradebook-by-opp.html b/course/templates/course/gradebook-by-opp.html index 3b1a7bdb3..8a48cb541 100644 --- a/course/templates/course/gradebook-by-opp.html +++ b/course/templates/course/gradebook-by-opp.html @@ -225,7 +225,7 @@

{% trans "Modify many sessions at once" %}

"paging": false, "ordering": true, "columnDefs": [{ type: 'name', targets: 1 }], - "language": {url: '{% static "datatables.net-plugins/i18n/" %}{{LANG}}.lang'}, + "language": {url: '{% static "datatables-i18n/i18n/" %}{{LANG}}.json'}, } ); new $.fn.dataTable.FixedColumns(tbl); diff --git a/course/templates/course/gradebook-opp-list.html b/course/templates/course/gradebook-opp-list.html index 55294cb54..06f3b83d7 100644 --- a/course/templates/course/gradebook-opp-list.html +++ b/course/templates/course/gradebook-opp-list.html @@ -76,7 +76,7 @@

{% trans "List of Grading Opportunities" %}

"scrollCollapse": true, "paging": false, "ordering": true, - "language": {url: '{% static "datatables.net-plugins/i18n/" %}{{LANG}}.lang'}, + "language": {url: '{% static "datatables-i18n/i18n/" %}{{LANG}}.json'}, } ); diff --git a/course/templates/course/gradebook-participant.html b/course/templates/course/gradebook-participant.html index ea4e15e5a..68a4a2a90 100644 --- a/course/templates/course/gradebook-participant.html +++ b/course/templates/course/gradebook-participant.html @@ -95,7 +95,7 @@

{% trans "Grades" %}

"scrollCollapse": true, "paging": false, "columnDefs": [{ type: 'name', targets: 1 }], - "language": {url: '{% static "datatables.net-plugins/i18n/" %}{{LANG}}.lang'}, + "language": {url: '{% static "datatables-i18n/i18n/" %}{{LANG}}.json'}, } ); diff --git a/course/templates/course/gradebook.html b/course/templates/course/gradebook.html index 0f1241f6b..48154c704 100644 --- a/course/templates/course/gradebook.html +++ b/course/templates/course/gradebook.html @@ -77,7 +77,7 @@

{% trans "Grade book" %}

"paging": true, "ordering": true, "columnDefs": [{ type: 'name', targets: 1 }], - "language": {url: '{% static "datatables.net-plugins/i18n/" %}{{LANG}}.lang'}, + "language": {url: '{% static "datatables-i18n/i18n/" %}{{LANG}}.json'}, } ); new $.fn.dataTable.FixedColumns(tbl); diff --git a/course/templates/course/participation-table.html b/course/templates/course/participation-table.html index aca66352c..bde4c58eb 100644 --- a/course/templates/course/participation-table.html +++ b/course/templates/course/participation-table.html @@ -64,6 +64,6 @@ "paging": false, "ordering": true, "columnDefs": [{ type: 'name', targets: 1 }], - "language": {url: '{% static "datatables.net-plugins/i18n/" %}{{LANG}}.lang'}, + "language": {url: '{% static "datatables-i18n/i18n/" %}{{LANG}}.json'}, } ); diff --git a/course/templatetags/coursetags.py b/course/templatetags/coursetags.py index aba4d2d4f..b4f12d112 100644 --- a/course/templatetags/coursetags.py +++ b/course/templatetags/coursetags.py @@ -24,20 +24,20 @@ from django.template import Library, Node, TemplateSyntaxError from django.utils import translation -from relate.utils import to_datatables_lang_name register = Library() -# {{{ get language_code in JS traditional naming format +# {{{ get language_code in JS traditional naming format class GetCurrentLanguageJsFmtNode(Node): def __init__(self, variable): self.variable = variable def render(self, context): - datatables_lang_name = to_datatables_lang_name(translation.get_language()) - context[self.variable] = datatables_lang_name + lang_name = ( + translation.to_locale(translation.get_language()).replace("_", "-")) + context[self.variable] = lang_name return '' @@ -46,9 +46,10 @@ def do_get_current_js_lang_name(parser, token): """ This will store the current language in the context, in js lang format. This is different with built-in do_get_current_language, which returns - languange name like "en-us", "zh-cn", with the country code using lower - case. This method return lang name "en-US", "zh-CN", as most js packages - with i18n are providing translations using that naming format. + languange name like "en-us", "zh-hans". This method return lang name + "en-US", "zh-Hans", with the country code capitallized if country code + has 2 characters, and capitalize first if country code has more than 2 + characters. Usage:: @@ -65,6 +66,25 @@ def do_get_current_js_lang_name(parser, token): "'as variable' (got %r)" % args) return GetCurrentLanguageJsFmtNode(args[2]) + +@register.filter(name='js_lang_fallback') +def js_lang_fallback(lang_name, js_name=None): + """ + Return the fallback lang name for js files. + :param a :class:`str:` + :param js_name: a :class:`str:`, optional. + :return: a :class:`str:` + """ + + # The mapping is crap, we use a special case table to fix it. + if js_name == "fullcalendar": + known_fallback_mapping = { + "zh-hans": "zh-cn", + "zh-hant": "zh-tw"} + return known_fallback_mapping.get(lang_name.lower(), lang_name).lower() + + return lang_name + # }}} diff --git a/package.json b/package.json index 49e8d5356..7f3613cc7 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "datatables.net-bs": "^1.10.16", "datatables.net-fixedcolumns": "^3.2.4", "datatables.net-fixedcolumns-bs": "^3.2.4", - "datatables.net-plugins": "^1.10.15", + "datatables-i18n": "git+https://github.com/dzhuang/datatables-i18n.git", "font-awesome": "^4.7.0", "fullcalendar": "^2.9.1", "jquery": "^3.3.1", diff --git a/relate/utils.py b/relate/utils.py index 6408afff0..a89658702 100644 --- a/relate/utils.py +++ b/relate/utils.py @@ -31,7 +31,6 @@ import django.forms as forms from django.utils.translation import ugettext_lazy as _ import dulwich.repo -import pycountry from typing import Union @@ -369,29 +368,6 @@ def dumpstacks(signal, frame): # }}} -# {{{ convert django language name to js styled language name - -def to_datatables_lang_name(dj_lang_name): - """ - Turns a Django language name (en-us) into the correspnding DataTables.net - i18n lang name. - """ - # The mapping is crap, we use a special case table to fix it. - mapping = {"zh-hans": "Chinese", - "zh-hant": "Chinese-traditional"} - - if dj_lang_name in mapping: - return mapping[dj_lang_name] - else: - primary = dj_lang_name.split('-')[0] - try: - return pycountry.languages.get(alpha_2=primary).name - except LookupError: - return "English" - -# }}} - - #{{{ Allow multiple email connections # https://gist.github.com/niran/840999 diff --git a/requirements.txt b/requirements.txt index 503328bac..2532b366a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -62,9 +62,6 @@ unicodecsv # To support network matching for facility recognition ipaddress -# For datatables i18n -pycountry - # {{{ For interoperation with SAML2/Shibboleth pysaml2 diff --git a/setup.py b/setup.py index fca3ff8ab..64eee057b 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,6 @@ "nbconvert>=5.2.1", "pymbolic", "sympy", - "pycountry", ], package_data={ "relate": [ diff --git a/tests/test_misc.py b/tests/test_misc.py index b6dcc4070..0e2a60d91 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -277,13 +277,25 @@ def test_get_current_js_lang_name_tag(self): template = self.engines["django"].from_string( "{% get_current_js_lang_name as LANG %}{{LANG}}") text = template.render() - self.assertEqual(text, "English") + self.assertEqual(text, "en-US") with override_settings(LANGUAGE_CODE="de"): template = self.engines["django"].from_string( "{% get_current_js_lang_name as LANG %}{{LANG}}") text = template.render() - self.assertEqual(text, "German") + self.assertEqual(text, "de") + + with override_settings(LANGUAGE_CODE="zh-hans"): + template = self.engines["django"].from_string( + "{% get_current_js_lang_name as LANG %}{{LANG}}") + text = template.render() + self.assertEqual(text, "zh-Hans") + + with override_settings(LANGUAGE_CODE="zh-hant"): + template = self.engines["django"].from_string( + "{% get_current_js_lang_name as LANG %}{{LANG}}") + text = template.render() + self.assertEqual(text, "zh-Hant") def test_get_current_js_lang_name_tag_failed(self): from django.template import TemplateSyntaxError @@ -307,6 +319,49 @@ def test_get_current_js_lang_name_tag_failed(self): self.engines["django"].from_string( "{% get_current_js_lang_name AS LANG %}{{LANG}}") + def test_js_lang_fallback(self): + with override_settings(LANGUAGE_CODE="en-us"): + template = self.engines["django"].from_string( + "{% get_current_js_lang_name as LANG %}" + "{{LANG|js_lang_fallback}}") + text = template.render() + self.assertEqual(text, "en-US") + + with override_settings(LANGUAGE_CODE="en-us"): + template = self.engines["django"].from_string( + "{% get_current_js_lang_name as LANG %}" + "{{LANG|js_lang_fallback:'fullcalendar'}}") + text = template.render() + self.assertEqual(text, "en-us") + + with override_settings(LANGUAGE_CODE="zh-cn"): + template = self.engines["django"].from_string( + "{% get_current_js_lang_name as LANG %}" + "{{LANG|js_lang_fallback:'fullcalendar'}}") + text = template.render() + self.assertEqual(text, "zh-cn") + + with override_settings(LANGUAGE_CODE="zh-cn"): + template = self.engines["django"].from_string( + "{% get_current_js_lang_name as LANG %}" + "{{LANG|js_lang_fallback}}") + text = template.render() + self.assertEqual(text, "zh-CN") + + with override_settings(LANGUAGE_CODE="zh-hans"): + template = self.engines["django"].from_string( + "{% get_current_js_lang_name as LANG %}" + "{{LANG|js_lang_fallback}}") + text = template.render() + self.assertEqual(text, "zh-Hans") + + with override_settings(LANGUAGE_CODE="zh-hans"): + template = self.engines["django"].from_string( + "{% get_current_js_lang_name as LANG %}" + "{{LANG|js_lang_fallback:'fullcalendar'}}") + text = template.render() + self.assertEqual(text, "zh-cn") + class HasPermissionTemplateFilterTest(SingleCourseTestMixin, TestCase): def setUp(self):