diff --git a/cms/static/coffee/files.json b/cms/static/coffee/files.json
index 3c27629f69..3964bee455 100644
--- a/cms/static/coffee/files.json
+++ b/cms/static/coffee/files.json
@@ -1,5 +1,6 @@
{
"static_files": [
+ "../jsi18n/",
"js/vendor/RequireJS.js",
"js/vendor/jquery.min.js",
"js/vendor/jquery-ui.min.js",
diff --git a/cms/static/js/base.js b/cms/static/js/base.js
index d597c2af27..f74a6cb5e4 100644
--- a/cms/static/js/base.js
+++ b/cms/static/js/base.js
@@ -79,10 +79,10 @@ $(document).ready(function() {
});
// general link management - new window/tab
- $('a[rel="external"]').attr('title', 'This link will open in a new browser window/tab').bind('click', linkNewWindow);
+ $('a[rel="external"]').attr('title', gettext('This link will open in a new browser window/tab')).bind('click', linkNewWindow);
// general link management - lean modal window
- $('a[rel="modal"]').attr('title', 'This link will open in a modal window').leanModal({
+ $('a[rel="modal"]').attr('title', gettext('This link will open in a modal window')).leanModal({
overlay: 0.50,
closeButton: '.action-modal-close'
});
@@ -199,8 +199,10 @@ function toggleSections(e) {
$section = $('.courseware-section');
sectionCount = $section.length;
$button = $(this);
- $labelCollapsed = $('
Collapse All Sections');
- $labelExpanded = $('
Expand All Sections');
+ $labelCollapsed = $('
' +
+ gettext('Collapse All Sections') + '');
+ $labelExpanded = $('
' +
+ gettext('Expand All Sections') + '');
var buttonLabel = $button.hasClass('is-activated') ? $labelCollapsed : $labelExpanded;
$button.toggleClass('is-activated').html(buttonLabel);
@@ -326,7 +328,7 @@ function saveSubsection() {
$changedInput = null;
},
error: function() {
- showToastMessage('There has been an error while saving your changes.');
+ showToastMessage(gettext('There has been an error while saving your changes.'));
}
});
}
@@ -372,7 +374,7 @@ function deleteSection(e) {
}
function _deleteItem($el) {
- if (!confirm('Are you sure you wish to delete this item. It cannot be reversed!')) return;
+ if (!confirm(gettext('Are you sure you wish to delete this item. It cannot be reversed!'))) return;
var id = $el.data('id');
@@ -599,7 +601,7 @@ function saveNewCourse(e) {
var display_name = $newCourse.find('.new-course-name').val();
if (org == '' || number == '' || display_name == '') {
- alert('You must specify all fields in order to create a new course.');
+ alert(gettext('You must specify all fields in order to create a new course.'));
return;
}
@@ -730,18 +732,16 @@ function saveSetSectionScheduleDate(e) {
})
}).success(function() {
var $thisSection = $('.courseware-section[data-id="' + id + '"]');
- var format = gettext('
Will Release: %(date)s at %(time)s UTC');
- var willReleaseAt = interpolate(format, {
- 'date': input_date,
- 'time': input_time
- },
- true);
- $thisSection.find('.section-published-date').html(
- '
' + willReleaseAt + '' +
- '
' + gettext('Edit') + '');
+ var html = _.template(
+ '
' +
+ '' + gettext("Will Release:") + '' +
+ gettext("<%= date %> at <%= time %> UTC") +
+ '' +
+ '
' +
+ gettext("Edit") +
+ '',
+ {date: input_date, time: input_time, id: id});
+ $thisSection.find('.section-published-date').html(html);
hideModal();
saving.hide();
});
diff --git a/cms/static/js/models/settings/course_details.js b/cms/static/js/models/settings/course_details.js
index 993832f830..d7e11d5689 100644
--- a/cms/static/js/models/settings/course_details.js
+++ b/cms/static/js/models/settings/course_details.js
@@ -38,23 +38,23 @@ CMS.Models.Settings.CourseDetails = Backbone.Model.extend({
// A bit funny in that the video key validation is asynchronous; so, it won't stop the validation.
var errors = {};
if (newattrs.start_date === null) {
- errors.start_date = "The course must have an assigned start date.";
+ errors.start_date = gettext("The course must have an assigned start date.");
}
if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) {
- errors.end_date = "The course end date cannot be before the course start date.";
+ errors.end_date = gettext("The course end date cannot be before the course start date.");
}
if (newattrs.start_date && newattrs.enrollment_start && newattrs.start_date < newattrs.enrollment_start) {
- errors.enrollment_start = "The course start date cannot be before the enrollment start date.";
+ errors.enrollment_start = gettext("The course start date cannot be before the enrollment start date.");
}
if (newattrs.enrollment_start && newattrs.enrollment_end && newattrs.enrollment_start >= newattrs.enrollment_end) {
- errors.enrollment_end = "The enrollment start date cannot be after the enrollment end date.";
+ errors.enrollment_end = gettext("The enrollment start date cannot be after the enrollment end date.");
}
if (newattrs.end_date && newattrs.enrollment_end && newattrs.end_date < newattrs.enrollment_end) {
- errors.enrollment_end = "The enrollment end date cannot be after the course end date.";
+ errors.enrollment_end = gettext("The enrollment end date cannot be after the course end date.");
}
if (newattrs.intro_video && newattrs.intro_video !== this.get('intro_video')) {
if (this._videokey_illegal_chars.exec(newattrs.intro_video)) {
- errors.intro_video = "Key should only contain letters, numbers, _, or -";
+ errors.intro_video = gettext("Key should only contain letters, numbers, _, or -");
}
// TODO check if key points to a real video using google's youtube api
}
diff --git a/cms/static/js/models/settings/course_grading_policy.js b/cms/static/js/models/settings/course_grading_policy.js
index 3014b39e82..04ae3f4c32 100644
--- a/cms/static/js/models/settings/course_grading_policy.js
+++ b/cms/static/js/models/settings/course_grading_policy.js
@@ -79,14 +79,14 @@ CMS.Models.Settings.CourseGrader = Backbone.Model.extend({
// FIXME somehow this.collection is unbound sometimes. I can't track down when
var existing = this.collection && this.collection.some(function(other) { return (other.cid != this.cid) && (other.get('type') == attrs['type']);}, this);
if (existing) {
- errors.type = "There's already another assignment type with this name.";
+ errors.type = gettext("There's already another assignment type with this name.");
}
}
}
if (_.has(attrs, 'weight')) {
var intWeight = parseInt(attrs.weight); // see if this ensures value saved is int
if (!isFinite(intWeight) || /\D+/.test(attrs.weight) || intWeight < 0 || intWeight > 100) {
- errors.weight = "Please enter an integer between 0 and 100.";
+ errors.weight = gettext("Please enter an integer between 0 and 100.");
}
else {
attrs.weight = intWeight;
@@ -100,18 +100,20 @@ CMS.Models.Settings.CourseGrader = Backbone.Model.extend({
}}
if (_.has(attrs, 'min_count')) {
if (!isFinite(attrs.min_count) || /\D+/.test(attrs.min_count)) {
- errors.min_count = "Please enter an integer.";
+ errors.min_count = gettext("Please enter an integer.");
}
else attrs.min_count = parseInt(attrs.min_count);
}
if (_.has(attrs, 'drop_count')) {
if (!isFinite(attrs.drop_count) || /\D+/.test(attrs.drop_count)) {
- errors.drop_count = "Please enter an integer.";
+ errors.drop_count = gettext("Please enter an integer.");
}
else attrs.drop_count = parseInt(attrs.drop_count);
}
if (_.has(attrs, 'min_count') && _.has(attrs, 'drop_count') && attrs.drop_count > attrs.min_count) {
- errors.drop_count = "Cannot drop more " + attrs.type + " than will assigned.";
+ errors.drop_count = _.template(
+ gettext("Cannot drop more <% attrs.types %> than will assigned."),
+ attrs, {variable: 'attrs'});
}
if (!_.isEmpty(errors)) return errors;
}
diff --git a/cms/static/js/views/textbook.js b/cms/static/js/views/textbook.js
index fe12082c7a..74eaae8601 100644
--- a/cms/static/js/views/textbook.js
+++ b/cms/static/js/views/textbook.js
@@ -26,8 +26,8 @@ CMS.Views.ShowTextbook = Backbone.View.extend({
if(e && e.preventDefault) { e.preventDefault(); }
var textbook = this.model, collection = this.model.collection;
var msg = new CMS.Views.Prompt.Warning({
- title: _.str.sprintf(gettext("Delete “%s”?"),
- textbook.escape('name')),
+ title: _.template(gettext("Delete “<%= name %>”?"),
+ {name: textbook.escape('name')}),
message: gettext("Deleting a textbook cannot be undone and once deleted any reference to it in your courseware's navigation will also be removed."),
actions: {
primary: {
@@ -241,8 +241,8 @@ CMS.Views.EditChapter = Backbone.View.extend({
asset_path: this.$("input.chapter-asset-path").val()
});
var msg = new CMS.Models.FileUpload({
- title: _.str.sprintf(gettext("Upload a new asset to %s"),
- section.escape('name')),
+ title: _.template(gettext("Upload a new asset to “<%= name %>”"),
+ {name: section.escape('name')}),
message: "Files must be in PDF format."
});
var view = new CMS.Views.UploadDialog({model: msg, chapter: this.model});
@@ -260,7 +260,7 @@ CMS.Views.UploadDialog = Backbone.View.extend({
this.listenTo(this.model, "change", this.render);
},
render: function() {
- var isValid = this.model.isValid()
+ var isValid = this.model.isValid();
var selectedFile = this.model.get('selectedFile');
var oldInput = this.$("input[type=file]").get(0);
this.$el.html(this.template({
diff --git a/cms/templates/404.html b/cms/templates/404.html
index a45a223bad..be7a66a31c 100644
--- a/cms/templates/404.html
+++ b/cms/templates/404.html
@@ -1,14 +1,19 @@
+<%! from django.utils.translation import ugettext as _ %>
<%inherit file="base.html" />
-<%block name="title">Page Not Found%block>
+<%block name="title">${_("Page Not Found")}%block>
<%block name="content">
- Page not found
- The page that you were looking for was not found. Go back to the homepage or let us know about any pages that may have been moved at technical@edx.org.
+ ${_("Page not found")}
+ ${_('The page that you were looking for was not found.')}
+ ${_('Go back to the {homepage} or let us know about any pages that may have been moved at {email}.').format(
+ homepage='homepage',
+ email='technical@edx.org')}
+
-%block>
\ No newline at end of file
+%block>
diff --git a/cms/templates/500.html b/cms/templates/500.html
index 3d18d9dcc5..5d79dd7a16 100644
--- a/cms/templates/500.html
+++ b/cms/templates/500.html
@@ -1,18 +1,19 @@
+<%! from django.utils.translation import ugettext as _ %>
<%inherit file="base.html" />
-<%block name="title">Studio Server Error%block>
+<%block name="title">${_("Studio Server Error")}%block>
<%block name="content">
- The Studio servers encountered an error
+ ${_("The Studio servers encountered an error")}
- An error occurred in Studio and the page could not be loaded. Please try again in a few moments.
- We've logged the error and our staff is currently working to resolve this error as soon as possible.
- If the problem persists, please email us at technical@edx.org.
+ ${_("An error occurred in Studio and the page could not be loaded. Please try again in a few moments.")}
+ ${_("We've logged the error and our staff is currently working to resolve this error as soon as possible.")}
+ ${_('If the problem persists, please email us at {email}.').format(email='technical@edx.org')}
-%block>
\ No newline at end of file
+%block>
diff --git a/cms/templates/activation_active.html b/cms/templates/activation_active.html
index 712c73abf9..9a4ebd7e4e 100644
--- a/cms/templates/activation_active.html
+++ b/cms/templates/activation_active.html
@@ -1,3 +1,4 @@
+<%! from django.utils.translation import ugettext as _ %>
<%inherit file="base.html" />
<%block name="content">
@@ -6,9 +7,9 @@
- Account already active!
- This account has already been activated. Log in here.
+ ${_("Account already active!")}
+ ${_('This account has already been activated.')}${_("Log in here.")}
-%block>
\ No newline at end of file
+%block>
diff --git a/cms/templates/activation_complete.html b/cms/templates/activation_complete.html
index 1e195a632c..d845c5153b 100644
--- a/cms/templates/activation_complete.html
+++ b/cms/templates/activation_complete.html
@@ -1,12 +1,13 @@
+<%! from django.utils.translation import ugettext as _ %>
<%inherit file="base.html" />
<%block name="content">
-
Activation Complete!
-
Thanks for activating your account. Log in here.
+
${_("Activation Complete!")}
+
${_('Thanks for activating your account.')}${_("Log in here.")}
-%block>
\ No newline at end of file
+%block>
diff --git a/cms/templates/activation_invalid.html b/cms/templates/activation_invalid.html
index c4eb16875b..3ee4e8ec4e 100644
--- a/cms/templates/activation_invalid.html
+++ b/cms/templates/activation_invalid.html
@@ -1,16 +1,15 @@
+<%! from django.utils.translation import ugettext as _ %>
<%inherit file="base.html" />
<%block name="content">
-
Activation Invalid
+
${_("Activation Invalid")}
-
Something went wrong. Check to make sure the URL you went to was
- correct -- e-mail programs will sometimes split it into two
- lines. If you still have issues, e-mail us to let us know what happened
- at bugs@mitx.mit.edu.
+
${_('Something went wrong. Check to make sure the URL you went to was correct -- e-mail programs will sometimes split it into two lines. If you still have issues, e-mail us to let us know what happened at {email}.').format(email='bugs@mitx.mit.edu')}
-
Or you can go back to the home page.
+
${_('Or you can go back to the {link_start}home page{link_end}.').format(
+ link_start='', link_end='')}
-%block>
\ No newline at end of file
+%block>
diff --git a/cms/templates/asset_index.html b/cms/templates/asset_index.html
index bdad7b7b88..6c92994a6f 100644
--- a/cms/templates/asset_index.html
+++ b/cms/templates/asset_index.html
@@ -2,7 +2,7 @@
<%! from django.core.urlresolvers import reverse %>
<%! from django.utils.translation import ugettext as _ %>
<%block name="bodyclass">is-signedin course uploads%block>
-<%block name="title">Files & Uploads%block>
+<%block name="title">${_("Files & Uploads")}%block>
<%namespace name='static' file='static_content.html'/>
@@ -48,7 +48,7 @@
Page Actions
diff --git a/cms/templates/base.html b/cms/templates/base.html
index e58dcdfc60..44ebf59170 100644
--- a/cms/templates/base.html
+++ b/cms/templates/base.html
@@ -1,3 +1,4 @@
+## -*- coding: utf-8 -*-
<%namespace name='static' file='static_content.html'/>
@@ -17,6 +18,7 @@
+
<%static:css group='base-style'/>
@@ -35,7 +37,6 @@
## javascript
-
diff --git a/cms/templates/checklists.html b/cms/templates/checklists.html
index 6f78e952c0..ad4f29aeb6 100644
--- a/cms/templates/checklists.html
+++ b/cms/templates/checklists.html
@@ -1,3 +1,4 @@
+<%! from django.utils.translation import ugettext as _ %>
<%inherit file="base.html" />
<%! from django.core.urlresolvers import reverse %>
<%block name="title">Course Checklists%block>
@@ -30,8 +31,8 @@
@@ -40,18 +41,18 @@