diff --git a/.jshintignore b/.jshintignore
index cd0d011354..5b3cf6d8c9 100644
--- a/.jshintignore
+++ b/.jshintignore
@@ -1,2 +1,4 @@
**/vendor
node_modules
+cms/static/js/i18n/**/*.js
+lms/static/js/i18n/**/*.js
diff --git a/cms/envs/common.py b/cms/envs/common.py
index 359d3c3dc8..7760d27e43 100644
--- a/cms/envs/common.py
+++ b/cms/envs/common.py
@@ -60,6 +60,8 @@ from lms.envs.common import (
# Django REST framework configuration
REST_FRAMEWORK,
+
+ STATICI18N_OUTPUT_DIR
)
from path import Path as path
from warnings import simplefilter
@@ -465,6 +467,8 @@ LANGUAGE_DICT = dict(LANGUAGES)
USE_I18N = True
USE_L10N = True
+STATICI18N_ROOT = PROJECT_ROOT / "static"
+
# Localization strings (e.g. django.po) are under this directory
LOCALE_PATHS = (REPO_ROOT + '/conf/locale',) # edx-platform/conf/locale/
@@ -845,6 +849,9 @@ INSTALLED_APPS = (
# edx-milestones service
'milestones',
+
+ # Static i18n support
+ 'statici18n',
)
diff --git a/cms/static/cms/js/require-config.js b/cms/static/cms/js/require-config.js
index 4ceb2635bd..167ed76174 100644
--- a/cms/static/cms/js/require-config.js
+++ b/cms/static/cms/js/require-config.js
@@ -1,289 +1,303 @@
-if (window) {
- // MathJax Fast Preview was introduced in 2.5. However, it
- // causes undesirable flashing/font size changes when
- // MathJax is used for interactive preview (equation editor).
- // Setting processSectionDelay to 0 (see below) fully eliminates
- // fast preview, but to reduce confusion, we are also setting
- // the option as displayed in the context menu to false.
- // When upgrading to 2.6, check if this variable name changed.
- window.MathJax = {
- menuSettings: {CHTMLpreview: false}
- };
-}
-
-require.config({
- // NOTE: baseUrl has been previously set in cms/static/templates/base.html
- waitSeconds: 60,
- paths: {
- "domReady": "js/vendor/domReady",
- "gettext": "/i18n",
- "mustache": "js/vendor/mustache",
- "codemirror": "js/vendor/codemirror-compressed",
- "codemirror/stex": "js/vendor/CodeMirror/stex",
- "jquery": "js/vendor/jquery.min",
- "jquery.ui": "js/vendor/jquery-ui.min",
- "jquery.form": "js/vendor/jquery.form",
- "jquery.markitup": "js/vendor/markitup/jquery.markitup",
- "jquery.leanModal": "js/vendor/jquery.leanModal",
- "jquery.ajaxQueue": "js/vendor/jquery.ajaxQueue",
- "jquery.smoothScroll": "js/vendor/jquery.smooth-scroll.min",
- "jquery.timepicker": "js/vendor/timepicker/jquery.timepicker",
- "jquery.cookie": "js/vendor/jquery.cookie",
- "jquery.qtip": "js/vendor/jquery.qtip.min",
- "jquery.scrollTo": "js/vendor/jquery.scrollTo-1.4.2-min",
- "jquery.flot": "js/vendor/flot/jquery.flot.min",
- "jquery.fileupload": "js/vendor/jQuery-File-Upload/js/jquery.fileupload",
- "jquery.fileupload-process": "js/vendor/jQuery-File-Upload/js/jquery.fileupload-process",
- "jquery.fileupload-validate": "js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate",
- "jquery.iframe-transport": "js/vendor/jQuery-File-Upload/js/jquery.iframe-transport",
- "jquery.inputnumber": "js/vendor/html5-input-polyfills/number-polyfill",
- "jquery.immediateDescendents": "coffee/src/jquery.immediateDescendents",
- "datepair": "js/vendor/timepicker/datepair",
- "date": "js/vendor/date",
- "moment": "js/vendor/moment.min",
- "moment-with-locales": "js/vendor/moment-with-locales.min",
- "text": 'js/vendor/requirejs/text',
- "underscore": "js/vendor/underscore-min",
- "underscore.string": "js/vendor/underscore.string.min",
- "backbone": "js/vendor/backbone-min",
- "backbone-relational" : "js/vendor/backbone-relational.min",
- "backbone.associations": "js/vendor/backbone-associations-min",
- "backbone.paginator": "js/vendor/backbone.paginator.min",
- "tinymce": "js/vendor/tinymce/js/tinymce/tinymce.full.min",
- "jquery.tinymce": "js/vendor/tinymce/js/tinymce/jquery.tinymce.min",
- "xmodule": "/xmodule/xmodule",
- "xblock/core": "js/xblock/core",
- "xblock": "coffee/src/xblock",
- "utility": "js/src/utility",
- "accessibility": "js/src/accessibility_tools",
- "draggabilly": "js/vendor/draggabilly.pkgd",
- "URI": "js/vendor/URI.min",
- "ieshim": "js/src/ie_shim",
- "tooltip_manager": "js/src/tooltip_manager",
-
- // Files needed for Annotations feature
- "annotator": "js/vendor/ova/annotator-full",
- "annotator-harvardx": "js/vendor/ova/annotator-full-firebase-auth",
- "video.dev": "js/vendor/ova/video.dev",
- "vjs.youtube": 'js/vendor/ova/vjs.youtube',
- "rangeslider": 'js/vendor/ova/rangeslider',
- "share-annotator": 'js/vendor/ova/share-annotator',
- "richText-annotator": 'js/vendor/ova/richText-annotator',
- "reply-annotator": 'js/vendor/ova/reply-annotator',
- "grouping-annotator": 'js/vendor/ova/grouping-annotator',
- "tags-annotator": 'js/vendor/ova/tags-annotator',
- "diacritic-annotator": 'js/vendor/ova/diacritic-annotator',
- "flagging-annotator": 'js/vendor/ova/flagging-annotator',
- "jquery-Watch": 'js/vendor/ova/jquery-Watch',
- "openseadragon": 'js/vendor/ova/openseadragon',
- "osda": 'js/vendor/ova/OpenSeaDragonAnnotation',
- "ova": 'js/vendor/ova/ova',
- "catch": 'js/vendor/ova/catch/js/catch',
- "handlebars": 'js/vendor/ova/catch/js/handlebars-1.1.2',
- // end of Annotation tool files
-
- // externally hosted files
- "mathjax": "//cdn.mathjax.org/mathjax/2.5-latest/MathJax.js?config=TeX-MML-AM_HTMLorMML-full&delayStartupUntil=configured",
- "youtube": [
- // youtube URL does not end in ".js". We add "?noext" to the path so
- // that require.js adds the ".js" to the query component of the URL,
- // and leaves the path component intact.
- "//www.youtube.com/player_api?noext",
- // if youtube fails to load, fallback on a local file
- // so that require doesn't fall over
- "js/src/youtube_fallback"
- ]
- },
- shim: {
- "gettext": {
- exports: "gettext"
- },
- "date": {
- exports: "Date"
- },
- "jquery.ui": {
- deps: ["jquery"],
- exports: "jQuery.ui"
- },
- "jquery.form": {
- deps: ["jquery"],
- exports: "jQuery.fn.ajaxForm"
- },
- "jquery.markitup": {
- deps: ["jquery"],
- exports: "jQuery.fn.markitup"
- },
- "jquery.leanmodal": {
- deps: ["jquery"],
- exports: "jQuery.fn.leanModal"
- },
- "jquery.ajaxQueue": {
- deps: ["jquery"],
- exports: "jQuery.fn.ajaxQueue"
- },
- "jquery.smoothScroll": {
- deps: ["jquery"],
- exports: "jQuery.fn.smoothScroll"
- },
- "jquery.cookie": {
- deps: ["jquery"],
- exports: "jQuery.fn.cookie"
- },
- "jquery.qtip": {
- deps: ["jquery"],
- exports: "jQuery.fn.qtip"
- },
- "jquery.scrollTo": {
- deps: ["jquery"],
- exports: "jQuery.fn.scrollTo",
- },
- "jquery.flot": {
- deps: ["jquery"],
- exports: "jQuery.fn.plot"
- },
- "jquery.fileupload": {
- deps: ["jquery.ui", "jquery.iframe-transport"],
- exports: "jQuery.fn.fileupload"
- },
- "jquery.fileupload-process": {
- deps: ["jquery.fileupload"]
- },
- "jquery.fileupload-validate": {
- deps: ["jquery.fileupload"]
- },
- "jquery.inputnumber": {
- deps: ["jquery"],
- exports: "jQuery.fn.inputNumber"
- },
- "jquery.tinymce": {
- deps: ["jquery", "tinymce"],
- exports: "jQuery.fn.tinymce"
- },
- "datepair": {
- deps: ["jquery.ui", "jquery.timepicker"]
- },
- "underscore": {
- exports: "_"
- },
- "backbone": {
- deps: ["underscore", "jquery"],
- exports: "Backbone"
- },
- "backbone.associations": {
- deps: ["backbone"],
- exports: "Backbone.Associations"
- },
- "backbone.paginator": {
- deps: ["backbone"],
- exports: "Backbone.Paginator"
- },
- "youtube": {
- exports: "YT"
- },
- "codemirror": {
- exports: "CodeMirror"
- },
- "codemirror/stex": {
- deps: ["codemirror"]
- },
- "tinymce": {
- exports: "tinymce"
- },
- "mathjax": {
- exports: "MathJax",
- init: function() {
- MathJax.Hub.Config({
- tex2jax: {
- inlineMath: [
- ["\\(","\\)"],
- ['[mathjaxinline]','[/mathjaxinline]']
- ],
- displayMath: [
- ["\\[","\\]"],
- ['[mathjax]','[/mathjax]']
- ]
- }
- });
- // In order to eliminate all flashing during interactive
- // preview, it is necessary to set processSectionDelay to 0
- // (remove delay between input and output phases). This
- // effectively disables fast preview, regardless of
- // the fast preview setting as shown in the context menu.
- MathJax.Hub.processSectionDelay = 0;
- MathJax.Hub.Configured();
- }
- },
- "URI": {
- exports: "URI"
- },
- "tooltip_manager": {
- deps: ["jquery", "underscore"]
- },
- "jquery.immediateDescendents": {
- deps: ["jquery"]
- },
- "xblock/core": {
- exports: "XBlock",
- deps: ["jquery", "jquery.immediateDescendents"]
- },
- "xblock/runtime.v1": {
- exports: "XBlock",
- deps: ["xblock/core"]
- },
-
- "coffee/src/main": {
- deps: ["coffee/src/ajax_prefix"]
- },
- "js/src/logger": {
- exports: "Logger",
- deps: ["coffee/src/ajax_prefix"]
- },
-
- // the following are all needed for annotation tools
- "video.dev": {
- exports:"videojs"
- },
- "vjs.youtube": {
- deps: ["video.dev"]
- },
- "rangeslider": {
- deps: ["video.dev"]
- },
- "annotator": {
- exports: "Annotator"
- },
- "annotator-harvardx":{
- deps: ["annotator"]
- },
- "share-annotator": {
- deps: ["annotator"]
- },
- "richText-annotator": {
- deps: ["annotator", "tinymce"]
- },
- "reply-annotator": {
- deps: ["annotator"]
- },
- "tags-annotator": {
- deps: ["annotator"]
- },
- "diacritic-annotator": {
- deps: ["annotator"]
- },
- "flagging-annotator": {
- deps: ["annotator"]
- },
- "grouping-annotator": {
- deps: ["annotator"]
- },
- "ova":{
- exports: "ova",
- deps: ["annotator", "annotator-harvardx", "video.dev", "vjs.youtube", "rangeslider", "share-annotator", "richText-annotator", "reply-annotator", "tags-annotator", "flagging-annotator", "grouping-annotator", "diacritic-annotator", "jquery-Watch", "catch", "handlebars", "URI"]
- },
- "osda":{
- exports: "osda",
- deps: ["annotator", "annotator-harvardx", "video.dev", "vjs.youtube", "rangeslider", "share-annotator", "richText-annotator", "reply-annotator", "tags-annotator", "flagging-annotator", "grouping-annotator", "diacritic-annotator", "openseadragon", "jquery-Watch", "catch", "handlebars", "URI"]
- }
- // end of annotation tool files
+;(function (require, define) {
+ 'use strict';
+ if (window) {
+ // MathJax Fast Preview was introduced in 2.5. However, it
+ // causes undesirable flashing/font size changes when
+ // MathJax is used for interactive preview (equation editor).
+ // Setting processSectionDelay to 0 (see below) fully eliminates
+ // fast preview, but to reduce confusion, we are also setting
+ // the option as displayed in the context menu to false.
+ // When upgrading to 2.6, check if this variable name changed.
+ window.MathJax = {
+ menuSettings: {CHTMLpreview: false}
+ };
+ // Since we are serving the gettext catalog as static files,
+ // the URL for the gettext file will vary depending on which locale
+ // needs to be served. To handle this, we load the correct file in the
+ // rendered template and then use this to ensure that RequireJS knows
+ // how to find it.
+ define("gettext", function () { return window.gettext; });
}
-});
+
+ require.config({
+ // NOTE: baseUrl has been previously set in cms/static/templates/base.html
+ waitSeconds: 60,
+ paths: {
+ "domReady": "js/vendor/domReady",
+ "mustache": "js/vendor/mustache",
+ "codemirror": "js/vendor/codemirror-compressed",
+ "codemirror/stex": "js/vendor/CodeMirror/stex",
+ "jquery": "js/vendor/jquery.min",
+ "jquery.ui": "js/vendor/jquery-ui.min",
+ "jquery.form": "js/vendor/jquery.form",
+ "jquery.markitup": "js/vendor/markitup/jquery.markitup",
+ "jquery.leanModal": "js/vendor/jquery.leanModal",
+ "jquery.ajaxQueue": "js/vendor/jquery.ajaxQueue",
+ "jquery.smoothScroll": "js/vendor/jquery.smooth-scroll.min",
+ "jquery.timepicker": "js/vendor/timepicker/jquery.timepicker",
+ "jquery.cookie": "js/vendor/jquery.cookie",
+ "jquery.qtip": "js/vendor/jquery.qtip.min",
+ "jquery.scrollTo": "js/vendor/jquery.scrollTo-1.4.2-min",
+ "jquery.flot": "js/vendor/flot/jquery.flot.min",
+ "jquery.fileupload": "js/vendor/jQuery-File-Upload/js/jquery.fileupload",
+ "jquery.fileupload-process": "js/vendor/jQuery-File-Upload/js/jquery.fileupload-process",
+ "jquery.fileupload-validate": "js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate",
+ "jquery.iframe-transport": "js/vendor/jQuery-File-Upload/js/jquery.iframe-transport",
+ "jquery.inputnumber": "js/vendor/html5-input-polyfills/number-polyfill",
+ "jquery.immediateDescendents": "coffee/src/jquery.immediateDescendents",
+ "datepair": "js/vendor/timepicker/datepair",
+ "date": "js/vendor/date",
+ "moment": "js/vendor/moment.min",
+ "moment-with-locales": "js/vendor/moment-with-locales.min",
+ "text": 'js/vendor/requirejs/text',
+ "underscore": "js/vendor/underscore-min",
+ "underscore.string": "js/vendor/underscore.string.min",
+ "backbone": "js/vendor/backbone-min",
+ "backbone-relational" : "js/vendor/backbone-relational.min",
+ "backbone.associations": "js/vendor/backbone-associations-min",
+ "backbone.paginator": "js/vendor/backbone.paginator.min",
+ "tinymce": "js/vendor/tinymce/js/tinymce/tinymce.full.min",
+ "jquery.tinymce": "js/vendor/tinymce/js/tinymce/jquery.tinymce.min",
+ "xmodule": "/xmodule/xmodule",
+ "xblock/core": "js/xblock/core",
+ "xblock": "coffee/src/xblock",
+ "utility": "js/src/utility",
+ "accessibility": "js/src/accessibility_tools",
+ "draggabilly": "js/vendor/draggabilly.pkgd",
+ "URI": "js/vendor/URI.min",
+ "ieshim": "js/src/ie_shim",
+ "tooltip_manager": "js/src/tooltip_manager",
+
+ // Files needed for Annotations feature
+ "annotator": "js/vendor/ova/annotator-full",
+ "annotator-harvardx": "js/vendor/ova/annotator-full-firebase-auth",
+ "video.dev": "js/vendor/ova/video.dev",
+ "vjs.youtube": 'js/vendor/ova/vjs.youtube',
+ "rangeslider": 'js/vendor/ova/rangeslider',
+ "share-annotator": 'js/vendor/ova/share-annotator',
+ "richText-annotator": 'js/vendor/ova/richText-annotator',
+ "reply-annotator": 'js/vendor/ova/reply-annotator',
+ "grouping-annotator": 'js/vendor/ova/grouping-annotator',
+ "tags-annotator": 'js/vendor/ova/tags-annotator',
+ "diacritic-annotator": 'js/vendor/ova/diacritic-annotator',
+ "flagging-annotator": 'js/vendor/ova/flagging-annotator',
+ "jquery-Watch": 'js/vendor/ova/jquery-Watch',
+ "openseadragon": 'js/vendor/ova/openseadragon',
+ "osda": 'js/vendor/ova/OpenSeaDragonAnnotation',
+ "ova": 'js/vendor/ova/ova',
+ "catch": 'js/vendor/ova/catch/js/catch',
+ "handlebars": 'js/vendor/ova/catch/js/handlebars-1.1.2',
+ // end of Annotation tool files
+
+ // externally hosted files
+ "mathjax": "//cdn.mathjax.org/mathjax/2.5-latest/MathJax.js?config=TeX-MML-AM_HTMLorMML-full&delayStartupUntil=configured", // jshint ignore:line
+ "youtube": [
+ // youtube URL does not end in ".js". We add "?noext" to the path so
+ // that require.js adds the ".js" to the query component of the URL,
+ // and leaves the path component intact.
+ "//www.youtube.com/player_api?noext",
+ // if youtube fails to load, fallback on a local file
+ // so that require doesn't fall over
+ "js/src/youtube_fallback"
+ ]
+ },
+ shim: {
+ "gettext": {
+ exports: "gettext"
+ },
+ "date": {
+ exports: "Date"
+ },
+ "jquery.ui": {
+ deps: ["jquery"],
+ exports: "jQuery.ui"
+ },
+ "jquery.form": {
+ deps: ["jquery"],
+ exports: "jQuery.fn.ajaxForm"
+ },
+ "jquery.markitup": {
+ deps: ["jquery"],
+ exports: "jQuery.fn.markitup"
+ },
+ "jquery.leanmodal": {
+ deps: ["jquery"],
+ exports: "jQuery.fn.leanModal"
+ },
+ "jquery.ajaxQueue": {
+ deps: ["jquery"],
+ exports: "jQuery.fn.ajaxQueue"
+ },
+ "jquery.smoothScroll": {
+ deps: ["jquery"],
+ exports: "jQuery.fn.smoothScroll"
+ },
+ "jquery.cookie": {
+ deps: ["jquery"],
+ exports: "jQuery.fn.cookie"
+ },
+ "jquery.qtip": {
+ deps: ["jquery"],
+ exports: "jQuery.fn.qtip"
+ },
+ "jquery.scrollTo": {
+ deps: ["jquery"],
+ exports: "jQuery.fn.scrollTo",
+ },
+ "jquery.flot": {
+ deps: ["jquery"],
+ exports: "jQuery.fn.plot"
+ },
+ "jquery.fileupload": {
+ deps: ["jquery.ui", "jquery.iframe-transport"],
+ exports: "jQuery.fn.fileupload"
+ },
+ "jquery.fileupload-process": {
+ deps: ["jquery.fileupload"]
+ },
+ "jquery.fileupload-validate": {
+ deps: ["jquery.fileupload"]
+ },
+ "jquery.inputnumber": {
+ deps: ["jquery"],
+ exports: "jQuery.fn.inputNumber"
+ },
+ "jquery.tinymce": {
+ deps: ["jquery", "tinymce"],
+ exports: "jQuery.fn.tinymce"
+ },
+ "datepair": {
+ deps: ["jquery.ui", "jquery.timepicker"]
+ },
+ "underscore": {
+ exports: "_"
+ },
+ "backbone": {
+ deps: ["underscore", "jquery"],
+ exports: "Backbone"
+ },
+ "backbone.associations": {
+ deps: ["backbone"],
+ exports: "Backbone.Associations"
+ },
+ "backbone.paginator": {
+ deps: ["backbone"],
+ exports: "Backbone.Paginator"
+ },
+ "youtube": {
+ exports: "YT"
+ },
+ "codemirror": {
+ exports: "CodeMirror"
+ },
+ "codemirror/stex": {
+ deps: ["codemirror"]
+ },
+ "tinymce": {
+ exports: "tinymce"
+ },
+ "mathjax": {
+ exports: "MathJax",
+ init: function() {
+ window.MathJax.Hub.Config({
+ tex2jax: {
+ inlineMath: [
+ ["\\(","\\)"],
+ ['[mathjaxinline]','[/mathjaxinline]']
+ ],
+ displayMath: [
+ ["\\[","\\]"],
+ ['[mathjax]','[/mathjax]']
+ ]
+ }
+ });
+ // In order to eliminate all flashing during interactive
+ // preview, it is necessary to set processSectionDelay to 0
+ // (remove delay between input and output phases). This
+ // effectively disables fast preview, regardless of
+ // the fast preview setting as shown in the context menu.
+ window.MathJax.Hub.processSectionDelay = 0;
+ window.MathJax.Hub.Configured();
+ }
+ },
+ "URI": {
+ exports: "URI"
+ },
+ "tooltip_manager": {
+ deps: ["jquery", "underscore"]
+ },
+ "jquery.immediateDescendents": {
+ deps: ["jquery"]
+ },
+ "xblock/core": {
+ exports: "XBlock",
+ deps: ["jquery", "jquery.immediateDescendents"]
+ },
+ "xblock/runtime.v1": {
+ exports: "XBlock",
+ deps: ["xblock/core"]
+ },
+
+ "coffee/src/main": {
+ deps: ["coffee/src/ajax_prefix"]
+ },
+ "js/src/logger": {
+ exports: "Logger",
+ deps: ["coffee/src/ajax_prefix"]
+ },
+
+ // the following are all needed for annotation tools
+ "video.dev": {
+ exports:"videojs"
+ },
+ "vjs.youtube": {
+ deps: ["video.dev"]
+ },
+ "rangeslider": {
+ deps: ["video.dev"]
+ },
+ "annotator": {
+ exports: "Annotator"
+ },
+ "annotator-harvardx":{
+ deps: ["annotator"]
+ },
+ "share-annotator": {
+ deps: ["annotator"]
+ },
+ "richText-annotator": {
+ deps: ["annotator", "tinymce"]
+ },
+ "reply-annotator": {
+ deps: ["annotator"]
+ },
+ "tags-annotator": {
+ deps: ["annotator"]
+ },
+ "diacritic-annotator": {
+ deps: ["annotator"]
+ },
+ "flagging-annotator": {
+ deps: ["annotator"]
+ },
+ "grouping-annotator": {
+ deps: ["annotator"]
+ },
+ "ova":{
+ exports: "ova",
+ deps: ["annotator", "annotator-harvardx", "video.dev", "vjs.youtube",
+ "rangeslider", "share-annotator", "richText-annotator", "reply-annotator",
+ "tags-annotator", "flagging-annotator", "grouping-annotator", "diacritic-annotator",
+ "jquery-Watch", "catch", "handlebars", "URI"]
+ },
+ "osda":{
+ exports: "osda",
+ deps: ["annotator", "annotator-harvardx", "video.dev", "vjs.youtube",
+ "rangeslider", "share-annotator", "richText-annotator", "reply-annotator",
+ "tags-annotator", "flagging-annotator", "grouping-annotator", "diacritic-annotator",
+ "openseadragon", "jquery-Watch", "catch", "handlebars", "URI"]
+ }
+ // end of annotation tool files
+ }
+ });
+}).call(this, require, define);
diff --git a/cms/templates/base.html b/cms/templates/base.html
index 9bacefda13..32ce03dcdd 100644
--- a/cms/templates/base.html
+++ b/cms/templates/base.html
@@ -23,6 +23,11 @@ from openedx.core.lib.js_utils import (
${settings.STUDIO_NAME}
+ <%
+ jsi18n_path = "js/i18n/{language}/djangojs.js".format(language=LANGUAGE_CODE)
+ %>
+
+
diff --git a/cms/urls.py b/cms/urls.py
index 5c3e8ed1cf..2b85e92471 100644
--- a/cms/urls.py
+++ b/cms/urls.py
@@ -122,12 +122,6 @@ JS_INFO_DICT = {
'packages': ('openassessment',),
}
-urlpatterns += patterns(
- '',
- # Serve catalog of localized strings to be rendered by Javascript
- url(r'^i18n.js$', 'django.views.i18n.javascript_catalog', JS_INFO_DICT),
-)
-
if settings.FEATURES.get('ENABLE_CONTENT_LIBRARIES'):
urlpatterns += (
url(r'^library/{}?$'.format(LIBRARY_KEY_PATTERN),
diff --git a/conf/locale/config.yaml b/conf/locale/config.yaml
index a029efc5da..d2410f6810 100644
--- a/conf/locale/config.yaml
+++ b/conf/locale/config.yaml
@@ -111,6 +111,9 @@ ignore_dirs:
- '*/spec'
- '*/tests'
- '*/features'
+ # Directories full of auto-generated JS
+ - lms/static/js/i18n
+ - cms/static/js/i18n
# Third-party installed apps that we also extract strings from. When adding a
diff --git a/lms/envs/common.py b/lms/envs/common.py
index 6ab46ebe0d..a1aae30155 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -922,6 +922,9 @@ LANGUAGE_DICT = dict(LANGUAGES)
USE_I18N = True
USE_L10N = True
+STATICI18N_ROOT = PROJECT_ROOT / "static"
+STATICI18N_OUTPUT_DIR = "js/i18n"
+
# Localization strings (e.g. django.po) are under this directory
LOCALE_PATHS = (REPO_ROOT + '/conf/locale',) # edx-platform/conf/locale/
# Messages
@@ -1943,6 +1946,9 @@ INSTALLED_APPS = (
# Gating of course content
'gating.apps.GatingConfig',
+
+ # Static i18n support
+ 'statici18n',
)
# Migrations which are not in the standard module "migrations"
diff --git a/lms/static/lms/js/require-config.js b/lms/static/lms/js/require-config.js
index acc0a3b3bc..2674176e7d 100644
--- a/lms/static/lms/js/require-config.js
+++ b/lms/static/lms/js/require-config.js
@@ -32,7 +32,6 @@
// NOTE: baseUrl has been previously set in lms/templates/main.html
waitSeconds: 60,
paths: {
- "gettext": "/i18n",
"annotator_1.2.9": "js/vendor/edxnotes/annotator-full.min",
"date": "js/vendor/date",
"moment": "js/vendor/moment.min",
diff --git a/lms/templates/main.html b/lms/templates/main.html
index 03c3b3f46c..0801da7e19 100644
--- a/lms/templates/main.html
+++ b/lms/templates/main.html
@@ -51,7 +51,11 @@ from branding import api as branding_api
% endif
-
+ <%
+ jsi18n_path = "js/i18n/{language}/djangojs.js".format(language=LANGUAGE_CODE)
+ %>
+
+
diff --git a/lms/urls.py b/lms/urls.py
index 3ea312edc2..f21f8821c0 100644
--- a/lms/urls.py
+++ b/lms/urls.py
@@ -138,11 +138,6 @@ js_info_dict = {
'packages': ('openassessment',),
}
-urlpatterns += (
- # Serve catalog of localized strings to be rendered by Javascript
- url(r'^i18n.js$', 'django.views.i18n.javascript_catalog', js_info_dict),
-)
-
# sysadmin dashboard, to see what courses are loaded, to delete & load courses
if settings.FEATURES["ENABLE_SYSADMIN_DASHBOARD"]:
urlpatterns += (
diff --git a/pavelib/i18n.py b/pavelib/i18n.py
index cd6ed7561c..cc7a622b2d 100644
--- a/pavelib/i18n.py
+++ b/pavelib/i18n.py
@@ -5,12 +5,15 @@ import sys
import subprocess
from path import Path as path
from paver.easy import task, cmdopts, needs, sh
+from .utils.cmd import django_cmd
try:
from pygments.console import colorize
except ImportError:
colorize = lambda color, text: text
+DEFAULT_SETTINGS = 'devstack'
+
@task
@needs(
@@ -194,6 +197,7 @@ def i18n_robot_pull():
"""
Pull source strings, generate po and mo files, and validate
"""
+
# sh('paver test_i18n')
# Tests were removed from repo, but there should still be tests covering the translations
# TODO: Validate the recently pulled translations, and give a bail option
@@ -203,10 +207,16 @@ def i18n_robot_pull():
print "\n\nValidating translations with `i18n_tool validate`..."
sh("{cmd}".format(cmd=cmd))
+ # Generate static i18n JS files.
+ for system in ['lms', 'cms']:
+ sh(django_cmd(system, DEFAULT_SETTINGS, 'compilejsi18n'))
+
con = raw_input("Continue with committing these translations (y/n)? ")
if con.lower() == 'y':
sh('git add conf/locale')
+ sh('git add cms/static/js/i18n')
+ sh('git add lms/static/js/i18n')
sh(
'git commit --message='
diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt
index 4ba13655e6..6c9d452cec 100644
--- a/requirements/edx/base.txt
+++ b/requirements/edx/base.txt
@@ -26,6 +26,7 @@ django-oauth-plus==2.2.8
django-sekizai==0.8.2
django-ses==0.7.0
django-simple-history==1.6.3
+django-statici18n==1.1.5
django-storages-redux==1.3
django-method-override==0.1.0
# We need a fix to DRF 3.2.x, for now use it from our own cherry-picked repo