Commit b7849799 by David Baumgold

Merge pull request #1792 from edx/man2life-i18n-no-forums

i18n (no forums)
parents 63a48114 03d7d0e9
...@@ -61,7 +61,7 @@ require(["domReady!", "jquery", "jquery.form", "js/index"], function(doc, $) { ...@@ -61,7 +61,7 @@ require(["domReady!", "jquery", "jquery.form", "js/index"], function(doc, $) {
<article class="content-primary" role="main"> <article class="content-primary" role="main">
<div class="introduction"> <div class="introduction">
<h2 class="title">${_("Welcome, {0}!".format(user.username))}</h2> <h2 class="title">${_("Welcome, {0}!").format(user.username)}</h2>
%if len(courses) > 0: %if len(courses) > 0:
<div class="copy"> <div class="copy">
......
...@@ -175,10 +175,12 @@ def instructor_dashboard(request, course_id): ...@@ -175,10 +175,12 @@ def instructor_dashboard(request, course_id):
student = User.objects.get(email=unique_student_identifier) student = User.objects.get(email=unique_student_identifier)
else: else:
student = User.objects.get(username=unique_student_identifier) student = User.objects.get(username=unique_student_identifier)
msg += "Found a single student. " msg += _u("Found a single student. ")
except User.DoesNotExist: except User.DoesNotExist:
student = None student = None
msg += "<font color='red'>Couldn't find student with that email or username. </font>" msg += "<font color='red'>{text}</font>".format(
text=_u("Couldn't find student with that email or username.")
)
return msg, student return msg, student
# process actions from form POST # process actions from form POST
...@@ -216,20 +218,20 @@ def instructor_dashboard(request, course_id): ...@@ -216,20 +218,20 @@ def instructor_dashboard(request, course_id):
if action == 'Dump list of enrolled students' or action == 'List enrolled students': if action == 'Dump list of enrolled students' or action == 'List enrolled students':
log.debug(action) log.debug(action)
datatable = get_student_grade_summary_data(request, course, course_id, get_grades=False, use_offline=use_offline) datatable = get_student_grade_summary_data(request, course, course_id, get_grades=False, use_offline=use_offline)
datatable['title'] = 'List of students enrolled in {0}'.format(course_id) datatable['title'] = _u('List of students enrolled in {0}').format(course_id)
track.views.server_track(request, "list-students", {}, page="idashboard") track.views.server_track(request, "list-students", {}, page="idashboard")
elif 'Dump Grades' in action: elif 'Dump Grades' in action:
log.debug(action) log.debug(action)
datatable = get_student_grade_summary_data(request, course, course_id, get_grades=True, use_offline=use_offline) datatable = get_student_grade_summary_data(request, course, course_id, get_grades=True, use_offline=use_offline)
datatable['title'] = 'Summary Grades of students enrolled in {0}'.format(course_id) datatable['title'] = _u('Summary Grades of students enrolled in {0}').format(course_id)
track.views.server_track(request, "dump-grades", {}, page="idashboard") track.views.server_track(request, "dump-grades", {}, page="idashboard")
elif 'Dump all RAW grades' in action: elif 'Dump all RAW grades' in action:
log.debug(action) log.debug(action)
datatable = get_student_grade_summary_data(request, course, course_id, get_grades=True, datatable = get_student_grade_summary_data(request, course, course_id, get_grades=True,
get_raw_scores=True, use_offline=use_offline) get_raw_scores=True, use_offline=use_offline)
datatable['title'] = 'Raw Grades of students enrolled in {0}'.format(course_id) datatable['title'] = _u('Raw Grades of students enrolled in {0}').format(course_id)
track.views.server_track(request, "dump-grades-raw", {}, page="idashboard") track.views.server_track(request, "dump-grades-raw", {}, page="idashboard")
elif 'Download CSV of all student grades' in action: elif 'Download CSV of all student grades' in action:
...@@ -257,14 +259,22 @@ def instructor_dashboard(request, course_id): ...@@ -257,14 +259,22 @@ def instructor_dashboard(request, course_id):
try: try:
instructor_task = submit_rescore_problem_for_all_students(request, course_id, problem_url) instructor_task = submit_rescore_problem_for_all_students(request, course_id, problem_url)
if instructor_task is None: if instructor_task is None:
msg += '<font color="red">Failed to create a background task for rescoring "{0}".</font>'.format(problem_url) msg += '<font color="red">{text}</font>'.format(
text=_u('Failed to create a background task for rescoring "{0}".').format(problem_url)
)
else: else:
track.views.server_track(request, "rescore-all-submissions", {"problem": problem_url, "course": course_id}, page="idashboard") track.views.server_track(request, "rescore-all-submissions", {"problem": problem_url, "course": course_id}, page="idashboard")
except ItemNotFoundError as err: except ItemNotFoundError as err:
msg += '<font color="red">Failed to create a background task for rescoring "{0}": problem not found.</font>'.format(problem_url) msg += '<font color="red">{text}</font>'.format(
text=_u('Failed to create a background task for rescoring "{0}": problem not found.').format(problem_url)
)
except Exception as err: except Exception as err:
log.error("Encountered exception from rescore: {0}".format(err)) log.error("Encountered exception from rescore: {0}".format(err))
msg += '<font color="red">Failed to create a background task for rescoring "{0}": {1}.</font>'.format(problem_url, err.message) msg += '<font color="red">{text}</font>'.format(
text=_u('Failed to create a background task for rescoring "{url}": {message}.').format(
url=problem_url, message=err.message
)
)
elif "Reset ALL students' attempts" in action: elif "Reset ALL students' attempts" in action:
problem_urlname = request.POST.get('problem_for_all_students', '') problem_urlname = request.POST.get('problem_for_all_students', '')
...@@ -272,15 +282,23 @@ def instructor_dashboard(request, course_id): ...@@ -272,15 +282,23 @@ def instructor_dashboard(request, course_id):
try: try:
instructor_task = submit_reset_problem_attempts_for_all_students(request, course_id, problem_url) instructor_task = submit_reset_problem_attempts_for_all_students(request, course_id, problem_url)
if instructor_task is None: if instructor_task is None:
msg += '<font color="red">Failed to create a background task for resetting "{0}".</font>'.format(problem_url) msg += '<font color="red">{text}</font>'.format(
text=_u('Failed to create a background task for resetting "{0}".').format(problem_url)
)
else: else:
track.views.server_track(request, "reset-all-attempts", {"problem": problem_url, "course": course_id}, page="idashboard") track.views.server_track(request, "reset-all-attempts", {"problem": problem_url, "course": course_id}, page="idashboard")
except ItemNotFoundError as err: except ItemNotFoundError as err:
log.error('Failure to reset: unknown problem "{0}"'.format(err)) log.error('Failure to reset: unknown problem "{0}"'.format(err))
msg += '<font color="red">Failed to create a background task for resetting "{0}": problem not found.</font>'.format(problem_url) msg += '<font color="red">{text}</font>'.format(
text=_u('Failed to create a background task for resetting "{0}": problem not found.').format(problem_url)
)
except Exception as err: except Exception as err:
log.error("Encountered exception from reset: {0}".format(err)) log.error("Encountered exception from reset: {0}".format(err))
msg += '<font color="red">Failed to create a background task for resetting "{0}": {1}.</font>'.format(problem_url, err.message) msg += '<font color="red">{text}</font>'.format(
text=_u('Failed to create a background task for resetting "{url}": {message}.').format(
url=problem_url, message=err.message
)
)
elif "Show Background Task History for Student" in action: elif "Show Background Task History for Student" in action:
# put this before the non-student case, since the use of "in" will cause this to be missed # put this before the non-student case, since the use of "in" will cause this to be missed
...@@ -321,12 +339,10 @@ def instructor_dashboard(request, course_id): ...@@ -321,12 +339,10 @@ def instructor_dashboard(request, course_id):
course_id=course_id, course_id=course_id,
module_state_key=module_state_key module_state_key=module_state_key
) )
msg += "Found module. " msg += _u("Found module. ")
except StudentModule.DoesNotExist as err: except StudentModule.DoesNotExist as err:
error_msg = "Couldn't find module with that urlname: {0}. ".format( error_msg = _u("Couldn't find module with that urlname: {url}. ").format(url=problem_urlname)
problem_urlname msg += "<font color='red'>{err_msg} ({err})</font>".format(err_msg=error_msg, err=err)
)
msg += "<font color='red'>" + error_msg + "({0}) ".format(err) + "</font>"
log.debug(error_msg) log.debug(error_msg)
if student_module is not None: if student_module is not None:
...@@ -334,7 +350,9 @@ def instructor_dashboard(request, course_id): ...@@ -334,7 +350,9 @@ def instructor_dashboard(request, course_id):
# delete the state # delete the state
try: try:
student_module.delete() student_module.delete()
msg += "<font color='red'>Deleted student module state for {0}!</font>".format(module_state_key) msg += "<font color='red'>{text}</font>".format(
text=_u("Deleted student module state for {state}!").format(state=module_state_key)
)
event = { event = {
"problem": module_state_key, "problem": module_state_key,
"student": unique_student_identifier, "student": unique_student_identifier,
...@@ -347,10 +365,10 @@ def instructor_dashboard(request, course_id): ...@@ -347,10 +365,10 @@ def instructor_dashboard(request, course_id):
page="idashboard" page="idashboard"
) )
except Exception as err: except Exception as err:
error_msg = "Failed to delete module state for {0}/{1}. ".format( error_msg = _u("Failed to delete module state for {id}/{url}. ").format(
unique_student_identifier, problem_urlname id=unique_student_identifier, url=problem_urlname
) )
msg += "<font color='red'>" + error_msg + "({0}) ".format(err) + "</font>" msg += "<font color='red'>{err_msg} ({err})</font>".format(err_msg=error_msg, err=err)
log.exception(error_msg) log.exception(error_msg)
elif "Reset student's attempts" in action: elif "Reset student's attempts" in action:
# modify the problem's state # modify the problem's state
...@@ -370,24 +388,32 @@ def instructor_dashboard(request, course_id): ...@@ -370,24 +388,32 @@ def instructor_dashboard(request, course_id):
"course": course_id "course": course_id
} }
track.views.server_track(request, "reset-student-attempts", event, page="idashboard") track.views.server_track(request, "reset-student-attempts", event, page="idashboard")
msg += "<font color='green'>Module state successfully reset!</font>" msg += "<font color='green'>{text}</font>".format(
text=_u("Module state successfully reset!")
)
except Exception as err: except Exception as err:
error_msg = "Couldn't reset module state for {0}/{1}. ".format( error_msg = _u("Couldn't reset module state for {id}/{url}. ").format(
unique_student_identifier, problem_urlname id=unique_student_identifier, url=problem_urlname
) )
msg += "<font color='red'>" + error_msg + "({0}) ".format(err) + "</font>" msg += "<font color='red'>{err_msg} ({err})</font>".format(err_msg=error_msg, err=err)
log.exception(error_msg) log.exception(error_msg)
else: else:
# "Rescore student's problem submission" case # "Rescore student's problem submission" case
try: try:
instructor_task = submit_rescore_problem_for_student(request, course_id, module_state_key, student) instructor_task = submit_rescore_problem_for_student(request, course_id, module_state_key, student)
if instructor_task is None: if instructor_task is None:
msg += '<font color="red">Failed to create a background task for rescoring "{0}" for student {1}.</font>'.format(module_state_key, unique_student_identifier) msg += '<font color="red">{text}</font>'.format(
text=_u('Failed to create a background task for rescoring "{key}" for student {id}.').format(
key=module_state_key, id=unique_student_identifier
)
)
else: else:
track.views.server_track(request, "rescore-student-submission", {"problem": module_state_key, "student": unique_student_identifier, "course": course_id}, page="idashboard") track.views.server_track(request, "rescore-student-submission", {"problem": module_state_key, "student": unique_student_identifier, "course": course_id}, page="idashboard")
except Exception as err: except Exception as err:
msg += '<font color="red">Failed to create a background task for rescoring "{0}": {1}.</font>'.format( msg += '<font color="red">{text}</font>'.format(
module_state_key, err.message text=_u('Failed to create a background task for rescoring "{key}": {id}.').format(
key=module_state_key, id=err.message
)
) )
log.exception("Encountered exception from rescore: student '{0}' problem '{1}'".format( log.exception("Encountered exception from rescore: student '{0}' problem '{1}'".format(
unique_student_identifier, module_state_key unique_student_identifier, module_state_key
...@@ -402,7 +428,12 @@ def instructor_dashboard(request, course_id): ...@@ -402,7 +428,12 @@ def instructor_dashboard(request, course_id):
if student is not None: if student is not None:
progress_url = reverse('student_progress', kwargs={'course_id': course_id, 'student_id': student.id}) progress_url = reverse('student_progress', kwargs={'course_id': course_id, 'student_id': student.id})
track.views.server_track(request, "get-student-progress-page", {"student": unicode(student), "instructor": unicode(request.user), "course": course_id}, page="idashboard") track.views.server_track(request, "get-student-progress-page", {"student": unicode(student), "instructor": unicode(request.user), "course": course_id}, page="idashboard")
msg += "<a href='{0}' target='_blank'> Progress page for username: {1} with email address: {2}</a>.".format(progress_url, student.username, student.email) msg += "<a href='{url}' target='_blank'>{text}</a>.".format(
url=progress_url,
text=_u("Progress page for username: {username} with email address: {email}").format(
username=student.username, email=student.email
)
)
#---------------------------------------- #----------------------------------------
# export grades to remote gradebook # export grades to remote gradebook
...@@ -416,7 +447,7 @@ def instructor_dashboard(request, course_id): ...@@ -416,7 +447,7 @@ def instructor_dashboard(request, course_id):
allgrades = get_student_grade_summary_data(request, course, course_id, get_grades=True, use_offline=use_offline) allgrades = get_student_grade_summary_data(request, course, course_id, get_grades=True, use_offline=use_offline)
assignments = [[x] for x in allgrades['assignments']] assignments = [[x] for x in allgrades['assignments']]
datatable = {'header': ['Assignment Name']} datatable = {'header': [_u('Assignment Name')]}
datatable['data'] = assignments datatable['data'] = assignments
datatable['title'] = action datatable['title'] = action
...@@ -440,27 +471,31 @@ def instructor_dashboard(request, course_id): ...@@ -440,27 +471,31 @@ def instructor_dashboard(request, course_id):
datatable = {} datatable = {}
aname = request.POST.get('assignment_name', '') aname = request.POST.get('assignment_name', '')
if not aname: if not aname:
msg += "<font color='red'>Please enter an assignment name</font>" msg += "<font color='red'>{text}</font>".format(text=_u("Please enter an assignment name"))
else: else:
allgrades = get_student_grade_summary_data(request, course, course_id, get_grades=True, use_offline=use_offline) allgrades = get_student_grade_summary_data(request, course, course_id, get_grades=True, use_offline=use_offline)
if aname not in allgrades['assignments']: if aname not in allgrades['assignments']:
msg += "<font color='red'>Invalid assignment name '%s'</font>" % aname msg += "<font color='red'>{text}</font>".format(
text=_u("Invalid assignment name '{name}'").format(name=aname)
)
else: else:
aidx = allgrades['assignments'].index(aname) aidx = allgrades['assignments'].index(aname)
datatable = {'header': ['External email', aname]} datatable = {'header': [_u('External email'), aname]}
ddata = [] ddata = []
for x in allgrades['students']: # do one by one in case there is a student who has only partial grades for x in allgrades['students']: # do one by one in case there is a student who has only partial grades
try: try:
ddata.append([x.email, x.grades[aidx]]) ddata.append([x.email, x.grades[aidx]])
except IndexError: except IndexError:
log.debug('No grade for assignment %s (%s) for student %s', aidx, aname, x.email) log.debug('No grade for assignment {idx} ({name}) for student {email}'.format(
idx=aidx, name=aname, email=x.email)
)
datatable['data'] = ddata datatable['data'] = ddata
datatable['title'] = 'Grades for assignment "%s"' % aname datatable['title'] = _u('Grades for assignment "{name}"').format(name=aname)
if 'Export CSV' in action: if 'Export CSV' in action:
# generate and return CSV file # generate and return CSV file
return return_csv('grades %s.csv' % aname, datatable) return return_csv('grades {name}.csv'.format(name=aname), datatable)
elif 'remote gradebook' in action: elif 'remote gradebook' in action:
file_pointer = StringIO() file_pointer = StringIO()
...@@ -475,12 +510,12 @@ def instructor_dashboard(request, course_id): ...@@ -475,12 +510,12 @@ def instructor_dashboard(request, course_id):
elif 'List course staff' in action: elif 'List course staff' in action:
role = CourseStaffRole(course.location) role = CourseStaffRole(course.location)
datatable = _role_members_table(role, "List of Staff", course_id) datatable = _role_members_table(role, _("List of Staff"), course_id)
track.views.server_track(request, "list-staff", {}, page="idashboard") track.views.server_track(request, "list-staff", {}, page="idashboard")
elif 'List course instructors' in action and GlobalStaff().has_user(request.user): elif 'List course instructors' in action and GlobalStaff().has_user(request.user):
role = CourseInstructorRole(course.location) role = CourseInstructorRole(course.location)
datatable = _role_members_table(role, "List of Instructors", course_id) datatable = _role_members_table(role, _("List of Instructors"), course_id)
track.views.server_track(request, "list-instructors", {}, page="idashboard") track.views.server_track(request, "list-instructors", {}, page="idashboard")
elif action == 'Add course staff': elif action == 'Add course staff':
...@@ -520,8 +555,8 @@ def instructor_dashboard(request, course_id): ...@@ -520,8 +555,8 @@ def instructor_dashboard(request, course_id):
return [u.username, u.email] + [getattr(p, x, '') for x in profkeys] return [u.username, u.email] + [getattr(p, x, '') for x in profkeys]
datatable['data'] = [getdat(u) for u in enrolled_students] datatable['data'] = [getdat(u) for u in enrolled_students]
datatable['title'] = 'Student profile data for course %s' % course_id datatable['title'] = _u('Student profile data for course {couse_id}').format(course_id = course_id)
return return_csv('profiledata_%s.csv' % course_id, datatable) return return_csv('profiledata_{course_id}.csv'.format(course_id = course_id), datatable)
elif 'Download CSV of all responses to problem' in action: elif 'Download CSV of all responses to problem' in action:
problem_to_dump = request.POST.get('problem_to_dump', '') problem_to_dump = request.POST.get('problem_to_dump', '')
...@@ -534,17 +569,19 @@ def instructor_dashboard(request, course_id): ...@@ -534,17 +569,19 @@ def instructor_dashboard(request, course_id):
smdat = StudentModule.objects.filter(course_id=course_id, smdat = StudentModule.objects.filter(course_id=course_id,
module_state_key=module_state_key) module_state_key=module_state_key)
smdat = smdat.order_by('student') smdat = smdat.order_by('student')
msg += "Found %d records to dump " % len(smdat) msg += _u("Found {num} records to dump.").format(num=smdat)
except Exception as err: except Exception as err:
msg += "<font color='red'>Couldn't find module with that urlname. </font>" msg += "<font color='red'>{text}</font><pre>{err}</pre>".format(
msg += "<pre>%s</pre>" % escape(err) text=_u("Couldn't find module with that urlname."),
err=escape(err)
)
smdat = [] smdat = []
if smdat: if smdat:
datatable = {'header': ['username', 'state']} datatable = {'header': ['username', 'state']}
datatable['data'] = [[x.student.username, x.state] for x in smdat] datatable['data'] = [[x.student.username, x.state] for x in smdat]
datatable['title'] = 'Student state for problem %s' % problem_to_dump datatable['title'] = _u('Student state for problem {problem}').format(problem = problem_to_dump)
return return_csv('student_state_from_%s.csv' % problem_to_dump, datatable) return return_csv('student_state_from_{problem}.csv'.format(problem = problem_to_dump), datatable)
elif 'Download CSV of all student anonymized IDs' in action: elif 'Download CSV of all student anonymized IDs' in action:
students = User.objects.filter( students = User.objects.filter(
...@@ -560,7 +597,7 @@ def instructor_dashboard(request, course_id): ...@@ -560,7 +597,7 @@ def instructor_dashboard(request, course_id):
elif 'List beta testers' in action: elif 'List beta testers' in action:
role = CourseBetaTesterRole(course.location) role = CourseBetaTesterRole(course.location)
datatable = _role_members_table(role, "List of Beta Testers", course_id) datatable = _role_members_table(role, _("List of Beta Testers"), course_id)
track.views.server_track(request, "list-beta-testers", {}, page="idashboard") track.views.server_track(request, "list-beta-testers", {}, page="idashboard")
elif action == 'Add beta testers': elif action == 'Add beta testers':
...@@ -699,9 +736,15 @@ def instructor_dashboard(request, course_id): ...@@ -699,9 +736,15 @@ def instructor_dashboard(request, course_id):
else: else:
# If sending the task succeeds, deliver a success message to the user. # If sending the task succeeds, deliver a success message to the user.
if email_to_option == "all": if email_to_option == "all":
email_msg = '<div class="msg msg-confirm"><p class="copy">Your email was successfully queued for sending. Please note that for large classes, it may take up to an hour (or more, if other courses are simultaneously sending email) to send all emails.</p></div>' text = _u(
"Your email was successfully queued for sending. "
"Please note that for large classes, it may take up to an hour "
"(or more, if other courses are simultaneously sending email) "
"to send all emails."
)
else: else:
email_msg = '<div class="msg msg-confirm"><p class="copy">Your email was successfully queued for sending.</p></div>' text = _u('Your email was successfully queued for sending.')
email_msg = '<div class="msg msg-confirm"><p class="copy">{text}</p></div>'.format(text=text)
elif "Show Background Email Task History" in action: elif "Show Background Email Task History" in action:
message, datatable = get_background_task_table(course_id, task_type='bulk_course_email') message, datatable = get_background_task_table(course_id, task_type='bulk_course_email')
...@@ -768,7 +811,11 @@ def instructor_dashboard(request, course_id): ...@@ -768,7 +811,11 @@ def instructor_dashboard(request, course_id):
# offline grades? # offline grades?
if use_offline: if use_offline:
msg += "<br/><font color='orange'>Grades from %s</font>" % offline_grades_available(course_id) msg += "<br/><font color='orange'>{text}</font>".format(
text=_u("Grades from {course_id}").format(
course_id=offline_grades_available(course_id)
)
)
# generate list of pending background tasks # generate list of pending background tasks
if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'): if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
...@@ -858,17 +905,17 @@ def _do_remote_gradebook(user, course, action, args=None, files=None): ...@@ -858,17 +905,17 @@ def _do_remote_gradebook(user, course, action, args=None, files=None):
''' '''
rg = course.remote_gradebook rg = course.remote_gradebook
if not rg: if not rg:
msg = "No remote gradebook defined in course metadata" msg = _u("No remote gradebook defined in course metadata")
return msg, {} return msg, {}
rgurl = settings.FEATURES.get('REMOTE_GRADEBOOK_URL', '') rgurl = settings.FEATURES.get('REMOTE_GRADEBOOK_URL', '')
if not rgurl: if not rgurl:
msg = "No remote gradebook url defined in settings.FEATURES" msg = _u("No remote gradebook url defined in settings.FEATURES")
return msg, {} return msg, {}
rgname = rg.get('name', '') rgname = rg.get('name', '')
if not rgname: if not rgname:
msg = "No gradebook name defined in course remote_gradebook metadata" msg = _u("No gradebook name defined in course remote_gradebook metadata")
return msg, {} return msg, {}
if args is None: if args is None:
...@@ -880,19 +927,19 @@ def _do_remote_gradebook(user, course, action, args=None, files=None): ...@@ -880,19 +927,19 @@ def _do_remote_gradebook(user, course, action, args=None, files=None):
resp = requests.post(rgurl, data=data, verify=False, files=files) resp = requests.post(rgurl, data=data, verify=False, files=files)
retdict = json.loads(resp.content) retdict = json.loads(resp.content)
except Exception as err: except Exception as err:
msg = "Failed to communicate with gradebook server at %s<br/>" % rgurl msg = _u("Failed to communicate with gradebook server at {url}").format(url = rgurl) + "<br/>"
msg += "Error: %s" % err msg += _u("Error: {err}").format(err = err)
msg += "<br/>resp=%s" % resp.content msg += "<br/>resp={resp}".format(resp = resp.content)
msg += "<br/>data=%s" % data msg += "<br/>data={data}".format(data = data)
return msg, {} return msg, {}
msg = '<pre>%s</pre>' % retdict['msg'].replace('\n', '<br/>') msg = '<pre>{msg}</pre>'.format(msg = retdict['msg'].replace('\n', '<br/>'))
retdata = retdict['data'] # a list of dicts retdata = retdict['data'] # a list of dicts
if retdata: if retdata:
datatable = {'header': retdata[0].keys()} datatable = {'header': retdata[0].keys()}
datatable['data'] = [x.values() for x in retdata] datatable['data'] = [x.values() for x in retdata]
datatable['title'] = 'Remote gradebook response for %s' % action datatable['title'] = _u('Remote gradebook response for {action}').format(action = action)
datatable['retdata'] = retdata datatable['retdata'] = retdata
else: else:
datatable = {} datatable = {}
...@@ -911,13 +958,13 @@ def _list_course_forum_members(course_id, rolename, datatable): ...@@ -911,13 +958,13 @@ def _list_course_forum_members(course_id, rolename, datatable):
Returns message status string to append to displayed message, if role is unknown. Returns message status string to append to displayed message, if role is unknown.
""" """
# make sure datatable is set up properly for display first, before checking for errors # make sure datatable is set up properly for display first, before checking for errors
datatable['header'] = ['Username', 'Full name', 'Roles'] datatable['header'] = [_u('Username'), _u('Full name'), _u('Roles')]
datatable['title'] = 'List of Forum {0}s in course {1}'.format(rolename, course_id) datatable['title'] = _u('List of Forum {name}s in course {id}').format(name = rolename, id = course_id)
datatable['data'] = [] datatable['data'] = []
try: try:
role = Role.objects.get(name=rolename, course_id=course_id) role = Role.objects.get(name=rolename, course_id=course_id)
except Role.DoesNotExist: except Role.DoesNotExist:
return '<font color="red">Error: unknown rolename "{0}"</font>'.format(rolename) return '<font color="red">' + _u('Error: unknown rolename "{0}"').format(rolename) + '</font>'
uset = role.users.all().order_by('username') uset = role.users.all().order_by('username')
msg = 'Role = {0}'.format(rolename) msg = 'Role = {0}'.format(rolename)
log.debug('role={0}'.format(rolename)) log.debug('role={0}'.format(rolename))
...@@ -941,11 +988,11 @@ def _update_forum_role_membership(uname, course, rolename, add_or_remove): ...@@ -941,11 +988,11 @@ def _update_forum_role_membership(uname, course, rolename, add_or_remove):
try: try:
user = User.objects.get(username=uname) user = User.objects.get(username=uname)
except User.DoesNotExist: except User.DoesNotExist:
return '<font color="red">Error: unknown username "{0}"</font>'.format(uname) return '<font color="red">' + _u('Error: unknown username "{0}"').format(uname) + '</font>'
try: try:
role = Role.objects.get(name=rolename, course_id=course.id) role = Role.objects.get(name=rolename, course_id=course.id)
except Role.DoesNotExist: except Role.DoesNotExist:
return '<font color="red">Error: unknown rolename "{0}"</font>'.format(rolename) return '<font color="red">' + _u('Error: unknown rolename "{0}"').format(rolename) + '</font>'
# check whether role already has the specified user: # check whether role already has the specified user:
alreadyexists = role.users.filter(username=uname).exists() alreadyexists = role.users.filter(username=uname).exists()
...@@ -953,19 +1000,19 @@ def _update_forum_role_membership(uname, course, rolename, add_or_remove): ...@@ -953,19 +1000,19 @@ def _update_forum_role_membership(uname, course, rolename, add_or_remove):
log.debug('rolename={0}'.format(rolename)) log.debug('rolename={0}'.format(rolename))
if add_or_remove == FORUM_ROLE_REMOVE: if add_or_remove == FORUM_ROLE_REMOVE:
if not alreadyexists: if not alreadyexists:
msg = '<font color="red">Error: user "{0}" does not have rolename "{1}", cannot remove</font>'.format(uname, rolename) msg = '<font color="red">' + _u('Error: user "{0}" does not have rolename "{1}", cannot remove').format(uname, rolename) + '</font>'
else: else:
user.roles.remove(role) user.roles.remove(role)
msg = '<font color="green">Removed "{0}" from "{1}" forum role = "{2}"</font>'.format(user, course.id, rolename) msg = '<font color="green">' + _u('Removed "{0}" from "{1}" forum role = "{2}"').format(user, course.id, rolename) + '</font>'
else: else:
if alreadyexists: if alreadyexists:
msg = '<font color="red">Error: user "{0}" already has rolename "{1}", cannot add</font>'.format(uname, rolename) msg = '<font color="red">' + _u('Error: user "{0}" already has rolename "{1}", cannot add').format(uname, rolename) + '</font>'
else: else:
if (rolename == FORUM_ROLE_ADMINISTRATOR and not has_access(user, course, 'staff')): if (rolename == FORUM_ROLE_ADMINISTRATOR and not has_access(user, course, 'staff')):
msg = '<font color="red">Error: user "{0}" should first be added as staff before adding as a forum administrator, cannot add</font>'.format(uname) msg = '<font color="red">' + _u('Error: user "{0}" should first be added as staff before adding as a forum administrator, cannot add').format(uname) + '</font>'
else: else:
user.roles.add(role) user.roles.add(role)
msg = '<font color="green">Added "{0}" to "{1}" forum role = "{2}"</font>'.format(user, course.id, rolename) msg = '<font color="green">' + _u('Added "{0}" to "{1}" forum role = "{2}"').format(user, course.id, rolename) + '</font>'
return msg return msg
...@@ -985,9 +1032,9 @@ def _role_members_table(role, title, course_id): ...@@ -985,9 +1032,9 @@ def _role_members_table(role, title, course_id):
'title': "{title} in course {course}" 'title': "{title} in course {course}"
""" """
uset = role.users_with_role() uset = role.users_with_role()
datatable = {'header': ['Username', 'Full name']} datatable = {'header': [_u('Username'), _u('Full name')]}
datatable['data'] = [[x.username, x.profile.name] for x in uset] datatable['data'] = [[x.username, x.profile.name] for x in uset]
datatable['title'] = '{0} in course {1}'.format(title, course_id) datatable['title'] = _u('{0} in course {1}').format(title, course_id)
return datatable return datatable
...@@ -1110,7 +1157,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True, ...@@ -1110,7 +1157,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True,
courseenrollment__is_active=1, courseenrollment__is_active=1,
).prefetch_related("groups").order_by('username') ).prefetch_related("groups").order_by('username')
header = ['ID', 'Username', 'Full Name', 'edX email', 'External email'] header = [_u('ID'), _u('Username'), _u('Full Name'), _u('edX email'), _u('External email')]
assignments = [] assignments = []
if get_grades and enrolled_students.count() > 0: if get_grades and enrolled_students.count() > 0:
# just to construct the header # just to construct the header
...@@ -1295,7 +1342,7 @@ def _do_enroll_students(course, course_id, students, overload=False, auto_enroll ...@@ -1295,7 +1342,7 @@ def _do_enroll_students(course, course_id, students, overload=False, auto_enroll
datatable = {'header': ['StudentEmail', 'action']} datatable = {'header': ['StudentEmail', 'action']}
datatable['data'] = [[x, status[x]] for x in sorted(status)] datatable['data'] = [[x, status[x]] for x in sorted(status)]
datatable['title'] = 'Enrollment of students' datatable['title'] = _u('Enrollment of students')
def sf(stat): def sf(stat):
return [x for x in status if status[x] == stat] return [x for x in status if status[x] == stat]
...@@ -1368,7 +1415,7 @@ def _do_unenroll_students(course_id, students, email_students=False): ...@@ -1368,7 +1415,7 @@ def _do_unenroll_students(course_id, students, email_students=False):
datatable = {'header': ['StudentEmail', 'action']} datatable = {'header': ['StudentEmail', 'action']}
datatable['data'] = [[x, status[x]] for x in sorted(status)] datatable['data'] = [[x, status[x]] for x in sorted(status)]
datatable['title'] = 'Un-enrollment of students' datatable['title'] = _u('Un-enrollment of students')
data = dict(datatable=datatable) data = dict(datatable=datatable)
return data return data
...@@ -1551,10 +1598,10 @@ def get_background_task_table(course_id, problem_url=None, student=None, task_ty ...@@ -1551,10 +1598,10 @@ def get_background_task_table(course_id, problem_url=None, student=None, task_ty
if problem_url is None: if problem_url is None:
msg += '<font color="red">Failed to find any background tasks for course "{course}".</font>'.format(course=course_id) msg += '<font color="red">Failed to find any background tasks for course "{course}".</font>'.format(course=course_id)
elif student is not None: elif student is not None:
template = '<font color="red">Failed to find any background tasks for course "{course}", module "{problem}" and student "{student}".</font>' template = '<font color="red">' + _u('Failed to find any background tasks for course "{course}", module "{problem}" and student "{student}".') + '</font>'
msg += template.format(course=course_id, problem=problem_url, student=student.username) msg += template.format(course=course_id, problem=problem_url, student=student.username)
else: else:
msg += '<font color="red">Failed to find any background tasks for course "{course}" and module "{problem}".</font>'.format(course=course_id, problem=problem_url) msg += '<font color="red">' + _u('Failed to find any background tasks for course "{course}" and module "{problem}".').format(course=course_id, problem=problem_url) + '</font>'
else: else:
datatable['header'] = ["Task Type", datatable['header'] = ["Task Type",
"Task Id", "Task Id",
......
...@@ -47,36 +47,36 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t ...@@ -47,36 +47,36 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t
''' '''
rubric: ''' rubric: '''
<table class="rubric"><tbody><tr><th>Purpose</th> <table class="rubric"><tbody><tr><th>Purpose</th>
<td> <td>
<input type="radio" class="score-selection" name="score-selection-0" id="score-0-0" value="0"><label for="score-0-0">No product</label> <input type="radio" class="score-selection" name="score-selection-0" id="score-0-0" value="0"><label for="score-0-0">No product</label>
</td> </td>
<td> <td>
<input type="radio" class="score-selection" name="score-selection-0" id="score-0-1" value="1"><label for="score-0-1">Unclear purpose or main idea</label> <input type="radio" class="score-selection" name="score-selection-0" id="score-0-1" value="1"><label for="score-0-1">Unclear purpose or main idea</label>
</td> </td>
<td> <td>
<input type="radio" class="score-selection" name="score-selection-0" id="score-0-2" value="2"><label for="score-0-2">Communicates an identifiable purpose and/or main idea for an audience</label> <input type="radio" class="score-selection" name="score-selection-0" id="score-0-2" value="2"><label for="score-0-2">Communicates an identifiable purpose and/or main idea for an audience</label>
</td> </td>
<td> <td>
<input type="radio" class="score-selection" name="score-selection-0" id="score-0-3" value="3"><label for="score-0-3">Achieves a clear and distinct purpose for a targeted audience and communicates main ideas with effectively used techniques to introduce and represent ideas and insights</label> <input type="radio" class="score-selection" name="score-selection-0" id="score-0-3" value="3"><label for="score-0-3">Achieves a clear and distinct purpose for a targeted audience and communicates main ideas with effectively used techniques to introduce and represent ideas and insights</label>
</td> </td>
</tr><tr><th>Organization</th> </tr><tr><th>Organization</th>
<td> <td>
<input type="radio" class="score-selection" name="score-selection-1" id="score-1-0" value="0"><label for="score-1-0">No product</label> <input type="radio" class="score-selection" name="score-selection-1" id="score-1-0" value="0"><label for="score-1-0">No product</label>
</td> </td>
<td> <td>
<input type="radio" class="score-selection" name="score-selection-1" id="score-1-1" value="1"><label for="score-1-1">Organization is unclear; introduction, body, and/or conclusion are underdeveloped, missing or confusing.</label> <input type="radio" class="score-selection" name="score-selection-1" id="score-1-1" value="1"><label for="score-1-1">Organization is unclear; introduction, body, and/or conclusion are underdeveloped, missing or confusing.</label>
</td> </td>
<td> <td>
<input type="radio" class="score-selection" name="score-selection-1" id="score-1-2" value="2"><label for="score-1-2">Organization is occasionally unclear; introduction, body or conclusion may be underdeveloped.</label> <input type="radio" class="score-selection" name="score-selection-1" id="score-1-2" value="2"><label for="score-1-2">Organization is occasionally unclear; introduction, body or conclusion may be underdeveloped.</label>
</td> </td>
<td> <td>
<input type="radio" class="score-selection" name="score-selection-1" id="score-1-3" value="3"><label for="score-1-3">Organization is clear and easy to follow; introduction, body and conclusion are defined and aligned with purpose.</label> <input type="radio" class="score-selection" name="score-selection-1" id="score-1-3" value="3"><label for="score-1-3">Organization is clear and easy to follow; introduction, body and conclusion are defined and aligned with purpose.</label>
</td> </td>
...@@ -98,9 +98,9 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t ...@@ -98,9 +98,9 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t
max_score: 2 + @mock_cnt % 3 max_score: 2 + @mock_cnt % 3
ml_error_info : 'ML accuracy info: ' + @mock_cnt ml_error_info : 'ML accuracy info: ' + @mock_cnt
else else
response = response =
success: false success: false
else if cmd == 'save_grade' else if cmd == 'save_grade'
response = response =
...@@ -109,7 +109,7 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t ...@@ -109,7 +109,7 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t
# should get back a list of problem_ids, problem_names, num_graded, min_for_ml # should get back a list of problem_ids, problem_names, num_graded, min_for_ml
else if cmd == 'get_problem_list' else if cmd == 'get_problem_list'
@mock_cnt = 1 @mock_cnt = 1
response = response =
success: true success: true
problem_list: [ problem_list: [
{location: 'i4x://MITx/3.091x/problem/open_ended_demo1', \ {location: 'i4x://MITx/3.091x/problem/open_ended_demo1', \
...@@ -123,7 +123,7 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t ...@@ -123,7 +123,7 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t
error: 'Unknown command ' + cmd error: 'Unknown command ' + cmd
if @mock_cnt % 5 == 0 if @mock_cnt % 5 == 0
response = response =
success: true success: true
message: 'No more submissions' message: 'No more submissions'
...@@ -132,7 +132,7 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t ...@@ -132,7 +132,7 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t
response = response =
success: false success: false
error: 'An error for testing' error: 'An error for testing'
return response return response
...@@ -190,7 +190,7 @@ class @StaffGrading ...@@ -190,7 +190,7 @@ class @StaffGrading
@question_header = $('.question-header') @question_header = $('.question-header')
@question_header.click @collapse_question @question_header.click @collapse_question
@collapse_question() @collapse_question()
# model state # model state
@state = state_no_data @state = state_no_data
@submission_id = null @submission_id = null
...@@ -266,7 +266,7 @@ class @StaffGrading ...@@ -266,7 +266,7 @@ class @StaffGrading
@render_view() @render_view()
@scroll_to_top() @scroll_to_top()
get_next_submission: (location) -> get_next_submission: (location) ->
@location = location @location = location
@list_view = false @list_view = false
...@@ -296,7 +296,7 @@ class @StaffGrading ...@@ -296,7 +296,7 @@ class @StaffGrading
submission_id: @submission_id submission_id: @submission_id
location: @location location: @location
submission_flagged: @flag_submission_checkbox.is(':checked') submission_flagged: @flag_submission_checkbox.is(':checked')
@gentle_alert "Grades saved. Fetching the next submission to grade." @gentle_alert gettext("Grades saved. Fetching the next submission to grade.")
@backend.post('save_grade', data, @ajax_callback) @backend.post('save_grade', data, @ajax_callback)
gentle_alert: (msg) => gentle_alert: (msg) =>
...@@ -344,13 +344,13 @@ class @StaffGrading ...@@ -344,13 +344,13 @@ class @StaffGrading
# clear the problem list and breadcrumbs # clear the problem list and breadcrumbs
@problem_list.html(''' @problem_list.html('''
<tr> <tr>
<th>Problem Name</th> <th>''' + gettext("Problem Name") + '''</th>
<th>Graded</th> <th>''' + gettext("Graded") + '''</th>
<th>Available to Grade</th> <th>''' + gettext("Available to Grade") + '''</th>
<th>Required</th> <th>''' + gettext("Required") + '''</th>
<th>Progress</th> <th>''' + gettext("Progress") + '''</th>
</tr> </tr>
''') ''')
@breadcrumbs.html('') @breadcrumbs.html('')
@problem_list_container.toggle(@list_view) @problem_list_container.toggle(@list_view)
if @backend.mock_backend if @backend.mock_backend
...@@ -364,14 +364,14 @@ class @StaffGrading ...@@ -364,14 +364,14 @@ class @StaffGrading
# only show the grading elements when we are not in list view or the state # only show the grading elements when we are not in list view or the state
# is invalid # is invalid
show_grading_elements = !(@list_view || @state == state_error || show_grading_elements = !(@list_view || @state == state_error ||
@state == state_no_data) @state == state_no_data)
@prompt_wrapper.toggle(show_grading_elements) @prompt_wrapper.toggle(show_grading_elements)
@submission_wrapper.toggle(show_grading_elements) @submission_wrapper.toggle(show_grading_elements)
@grading_wrapper.toggle(show_grading_elements) @grading_wrapper.toggle(show_grading_elements)
@meta_info_wrapper.toggle(show_grading_elements) @meta_info_wrapper.toggle(show_grading_elements)
@action_button.hide() @action_button.hide()
if @list_view if @list_view
@render_list() @render_list()
else else
...@@ -410,23 +410,27 @@ class @StaffGrading ...@@ -410,23 +410,27 @@ class @StaffGrading
show_action_button = true show_action_button = true
problem_list_link = $('<a>').attr('href', 'javascript:void(0);') problem_list_link = $('<a>').attr('href', 'javascript:void(0);')
.append("< Back to problem list") .append("< " + gettext("Back to problem list"))
.click => @get_problem_list() .click => @get_problem_list()
# set up the breadcrumbing # set up the breadcrumbing
@breadcrumbs.append(problem_list_link) @breadcrumbs.append(problem_list_link)
if @state == state_error if @state == state_error
@set_button_text('Try loading again') @set_button_text(gettext('Try loading again'))
show_action_button = true show_action_button = true
else if @state == state_grading else if @state == state_grading
@ml_error_info_container.html(@ml_error_info) @ml_error_info_container.html(@ml_error_info)
available = _.template(gettext("<%= num %> available"), {num: @num_pending})
graded = _.template(gettext("<%= num %> graded"), {num: @num_graded})
needed = _.template(gettext("<%= num %> more needed to start ML"),
{num: Math.max(@min_for_ml - @num_graded, 0)})
meta_list = $("<div>") meta_list = $("<div>")
meta_list.append("<div class='meta-info'>#{@num_pending} available | </div>") .append("<div class='meta-info'>#{available}</div>")
meta_list.append("<div class='meta-info'>#{@num_graded} graded | </div>") .append("<div class='meta-info'>#{graded}</div>")
meta_list.append("<div class='meta-info'>#{Math.max(@min_for_ml - @num_graded, 0)} more needed to start ML </div><br/>") .append("<div class='meta-info'>#{needed}</div>")
@problem_meta_info.html(meta_list) @problem_meta_info.html(meta_list)
@prompt_container.html(@prompt) @prompt_container.html(@prompt)
...@@ -437,24 +441,24 @@ class @StaffGrading ...@@ -437,24 +441,24 @@ class @StaffGrading
show_action_button = false show_action_button = false
@setup_score_selection() @setup_score_selection()
else if @state == state_graded else if @state == state_graded
@set_button_text('Submit') @set_button_text(gettext('Submit'))
show_action_button = false show_action_button = false
else if @state == state_no_data else if @state == state_no_data
@message_container.html(@message) @message_container.html(@message)
@set_button_text('Re-check for submissions') @set_button_text(gettext('Re-check for submissions'))
else else
@error('System got into invalid state ' + @state) @error(_.template(gettext('System got into invalid state: <%= state %>'), {state: @state}))
@submit_button.toggle(show_submit_button) @submit_button.toggle(show_submit_button)
@action_button.toggle(show_action_button) @action_button.toggle(show_action_button)
submit: (event) => submit: (event) =>
event.preventDefault() event.preventDefault()
if @state == state_error if @state == state_error
@get_next_submission(@location) @get_next_submission(@location)
else if @state == state_graded else if @state == state_graded
...@@ -462,17 +466,17 @@ class @StaffGrading ...@@ -462,17 +466,17 @@ class @StaffGrading
else if @state == state_no_data else if @state == state_no_data
@get_next_submission(@location) @get_next_submission(@location)
else else
@error('System got into invalid state for submission: ' + @state) @error(gettext('System got into invalid state for submission: ') + @state)
collapse_question: () => collapse_question: () =>
@prompt_container.slideToggle() @prompt_container.slideToggle()
@prompt_container.toggleClass('open') @prompt_container.toggleClass('open')
if @question_header.text() == "(Hide)" if @question_header.text() == gettext("(Hide)")
Logger.log 'staff_grading_hide_question', {location: @location} Logger.log 'staff_grading_hide_question', {location: @location}
new_text = "(Show)" new_text = gettext("(Show)")
else else
Logger.log 'staff_grading_show_question', {location: @location} Logger.log 'staff_grading_show_question', {location: @location}
new_text = "(Hide)" new_text = gettext("(Hide)")
@question_header.text(new_text) @question_header.text(new_text)
scroll_to_top: () => scroll_to_top: () =>
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
</div> </div>
% if is_staff: % if is_staff:
<div class="staff-info"> <div class="staff-info">
Staff Warning: Please note that if you submit a duplicate of text that has already been submitted for grading, it will not show up in the staff grading view. It will be given the same grade that the original received automatically, and will be returned within 30 minutes if the original is already graded, or when the original is graded if not. ${_("Staff Warning: Please note that if you submit a duplicate of text that has already been submitted for grading, it will not show up in the staff grading view. It will be given the same grade that the original received automatically, and will be returned within 30 minutes if the original is already graded, or when the original is graded if not.")}
</div> </div>
% endif % endif
</section> </section>
......
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
<%! from django.utils.translation import ungettext%>
<% from random import randint %> <% from random import randint %>
<form class="rubric-template" id="inputtype_${id}" xmlns="http://www.w3.org/1999/html"> <form class="rubric-template" id="inputtype_${id}" xmlns="http://www.w3.org/1999/html">
<div class="visibility-control visibility-control-rubric"> <div class="visibility-control visibility-control-rubric">
...@@ -6,7 +7,7 @@ ...@@ -6,7 +7,7 @@
</div> </div>
<span class="section-header section-header-rubric">${_("Rubric")}</span> <span class="section-header section-header-rubric">${_("Rubric")}</span>
</div> </div>
<p>Select the criteria you feel best represents this submission in each category.</p> <p>${_("Select the criteria you feel best represents this submission in each category.")}</p>
<div class="rubric"> <div class="rubric">
% for i in range(len(categories)): % for i in range(len(categories)):
<% category = categories[i] %> <% category = categories[i] %>
...@@ -22,7 +23,14 @@ ...@@ -22,7 +23,14 @@
% endif % endif
<label class="rubric-label" for="score-${i}-${j}-${m}"> <label class="rubric-label" for="score-${i}-${j}-${m}">
<span class="wrapper-score-selection"><input type="radio" class="score-selection" data-category="${i}" name="score-selection-${i}" id="score-${i}-${j}-${m}" value="${option['points']}"/></span> <span class="wrapper-score-selection"><input type="radio" class="score-selection" data-category="${i}" name="score-selection-${i}" id="score-${i}-${j}-${m}" value="${option['points']}"/></span>
<span class="wrappable"> ${option['points']} points : ${option['text']}</span> <span class="wrappable">${ungettext(
"{num} point: {text}",
"{num} points: {text}",
option['points']
).format(
num=option['points'],
text=option['text']
)}</span>
</label> </label>
</li> </li>
% endfor % endfor
......
## mako ## mako
<%! from django.utils.translation import ugettext as _ %>
<%page args="active_page=None" /> <%page args="active_page=None" />
<% <%
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
<tr> <tr>
<th> <th>
<form class="student-search"> <form class="student-search">
<input type="search" class="student-search-field" placeholder="Search students" /> <input type="search" class="student-search-field" placeholder="${_('Search students')}" />
</form> </form>
</th> </th>
</tr> </tr>
......
...@@ -59,7 +59,7 @@ ${progress_graph.body(grade_summary, course.grade_cutoffs, "grade-detail-graph", ...@@ -59,7 +59,7 @@ ${progress_graph.body(grade_summary, course.grade_cutoffs, "grade-detail-graph",
${ section['display_name'] } ${ section['display_name'] }
%if total > 0 or earned > 0: %if total > 0 or earned > 0:
<span class="sr"> <span class="sr">
${"{0:.3n} of {1:.3n} possible points".format( float(earned), float(total) )} ${_("{earned:.3n} of {total:.3n} possible points").format( earned = float(earned), total = float(total) )}
</span></a> </span></a>
%endif %endif
%if total > 0 or earned > 0: %if total > 0 or earned > 0:
...@@ -72,7 +72,7 @@ ${progress_graph.body(grade_summary, course.grade_cutoffs, "grade-detail-graph", ...@@ -72,7 +72,7 @@ ${progress_graph.body(grade_summary, course.grade_cutoffs, "grade-detail-graph",
%if section.get('due') is not None: %if section.get('due') is not None:
<% <%
formatted_string = get_time_display(section['due'], course.due_date_display_format) formatted_string = get_time_display(section['due'], course.due_date_display_format)
due_date = '' if len(formatted_string)==0 else _('due {date}'.format(date=formatted_string)) due_date = '' if len(formatted_string)==0 else _(u'due {date}').format(date=formatted_string)
%> %>
<em> <em>
${due_date} ${due_date}
...@@ -82,7 +82,7 @@ ${progress_graph.body(grade_summary, course.grade_cutoffs, "grade-detail-graph", ...@@ -82,7 +82,7 @@ ${progress_graph.body(grade_summary, course.grade_cutoffs, "grade-detail-graph",
<section class="scores"> <section class="scores">
%if len(section['scores']) > 0: %if len(section['scores']) > 0:
<h3> ${ "Problem Scores: " if section['graded'] else "Practice Scores: "} </h3> <h3> ${ _("Problem Scores: ") if section['graded'] else _("Practice Scores: ")} </h3>
<ol> <ol>
%for score in section['scores']: %for score in section['scores']:
<li>${"{0:.3n}/{1:.3n}".format(float(score.earned),float(score.possible))}</li> <li>${"{0:.3n}/{1:.3n}".format(float(score.earned),float(score.possible))}</li>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment