Commit 97f5b25e by Adam Palay

i18n for self-assessment (ORA-314)

make openendedchild and open_ended_module_v1 act enough like xblocks to get xblock 18n
parent d6f1ddd8
......@@ -812,7 +812,7 @@ class ChemicalEquationTest(unittest.TestCase):
def test_ajax_bad_method(self):
"""
With a bad dispatch, we shouldn't recieve anything
With a bad dispatch, we shouldn't receive anything
"""
response = self.the_input.handle_ajax("obviously_not_real", {})
self.assertEqual(response, {})
......@@ -923,7 +923,7 @@ class FormulaEquationTest(unittest.TestCase):
def test_ajax_bad_method(self):
"""
With a bad dispatch, we shouldn't recieve anything
With a bad dispatch, we shouldn't receive anything
"""
response = self.the_input.handle_ajax("obviously_not_real", {})
self.assertEqual(response, {})
......
......@@ -49,7 +49,7 @@ def segment_to_fraction(distance):
with nice fractions (which produce small Miller indices), he may want shift
to new origin if segments are like S = (0.015, > 0.05, >0.05) - close to zero
in one coordinate. He may update S to (0, >0.05, >0.05) and shift origin.
In this way he can recieve nice small fractions. Also there is can be
In this way he can receive nice small fractions. Also there is can be
degenerated case when S = (0.015, 0.012, >0.05) - if update S to (0, 0, >0.05) -
it is a line. This case should be considered separately. Small nice Miller
numbers and possibility to create very small segments can not be implemented
......
......@@ -249,7 +249,11 @@ class @CombinedOpenEnded
fd.append('submission_id', submission_id)
fd.append('grader_id', grader_id)
if(!score)
@gentle_alert "You need to pick a rating before you can submit."
###
Translators: A "rating" is a score a student gives to indicate how well
they feel they were graded on this problem
###
@gentle_alert gettext "You need to pick a rating before you can submit."
return
else
fd.append('score', score)
......@@ -293,10 +297,15 @@ class @CombinedOpenEnded
@replace_text_inputs()
@hint_area.attr('disabled', true)
if @task_number<@task_count
@gentle_alert "Your score did not meet the criteria to move to the next step."
###
Translators: this message appears when transitioning between openended grading
types (i.e. self assesment to peer assessment). Sometimes, if a student
did not perform well at one step, they cannot move on to the next one.
###
@gentle_alert gettext "Your score did not meet the criteria to move to the next step."
else if @child_state == 'initial'
@answer_area.attr("disabled", false)
@submit_button.prop('value', 'Submit')
@submit_button.prop('value', gettext 'Submit')
@submit_button.click @confirm_save_answer
@setup_file_upload()
@save_button.click @store_answer
......@@ -305,14 +314,18 @@ class @CombinedOpenEnded
@answer_area.attr("disabled", true)
@replace_text_inputs()
@hide_file_upload()
@submit_button.prop('value', 'Submit assessment')
###
Translators: one clicks this button after one has finished filling out the grading
form for an openended assessment
###
@submit_button.prop('value', gettext 'Submit assessment')
@submit_button.click @save_assessment
@submit_button.attr("disabled",true)
if @child_type == "openended"
@submit_button.hide()
@queueing()
@grader_status = @$(@grader_status_sel)
@grader_status.html("<span class='grading'>Your response has been submitted. Please check back later for your grade.</span>")
@grader_status.html("<span class='grading'>" + gettext "Your response has been submitted. Please check back later for your grade." + "</span>")
else if @child_type == "selfassessment"
@setup_score_selection()
else if @child_state == 'post_assessment'
......@@ -321,7 +334,11 @@ class @CombinedOpenEnded
@skip_post_assessment()
@answer_area.attr("disabled", true)
@replace_text_inputs()
@submit_button.prop('value', 'Submit post-assessment')
###
Translators: this button is clicked to submit a student's rating of
an evaluator's assessment
###
@submit_button.prop('value', gettext 'Submit post-assessment')
if @child_type=="selfassessment"
@submit_button.click @save_hint
else
......@@ -353,7 +370,7 @@ class @CombinedOpenEnded
@save_button.attr("disabled",true)
$.postWithPrefix "#{@ajax_url}/store_answer", data, (response) =>
if response.success
@gentle_alert("Answer saved, but not yet submitted.")
@gentle_alert(gettext "Answer saved, but not yet submitted.")
else
@errors_area.html(response.error)
@save_button.attr("disabled",false)
......@@ -378,7 +395,12 @@ class @CombinedOpenEnded
@gentle_alert response.error
confirm_save_answer: (event) =>
@save_answer(event) if confirm('Please confirm that you wish to submit your work. You will not be able to make any changes after submitting.')
###
Translators: This string appears in a confirmation box after one tries to submit
an openended problem
###
confirmation_text = gettext 'Please confirm that you wish to submit your work. You will not be able to make any changes after submitting.'
@save_answer(event) if confirm(confirmation_text)
save_answer: (event) =>
@$el.find(@oe_alert_sel).remove()
......@@ -399,7 +421,7 @@ class @CombinedOpenEnded
# Don't submit the file in the case of it being too large, deal with the error locally.
@submit_button.show()
@submit_button.attr('disabled', false)
@gentle_alert "You are trying to upload a file that is too large for our system. Please choose a file under 2MB or paste a link to it into the answer box."
@gentle_alert gettext "You are trying to upload a file that is too large for our system. Please choose a file under 2MB or paste a link to it into the answer box."
return
fd = new FormData()
......@@ -422,14 +444,14 @@ class @CombinedOpenEnded
@errors_area.html(@out_of_sync_message)
keydown_handler: (event) =>
#Previously, responses were submitted when hitting enter. Add in a modifier that ensures that ctrl+enter is needed.
# Previously, responses were submitted when hitting enter. Add in a modifier that ensures that ctrl+enter is needed.
if event.which == 17 && @is_ctrl==false
@is_ctrl=true
else if @is_ctrl==true && event.which == 13 && @child_state == 'assessing' && @rub.check_complete()
@save_assessment(event)
keyup_handler: (event) =>
#Handle keyup event when ctrl key is released
# Handle keyup event when ctrl key is released
if event.which == 17 && @is_ctrl==true
@is_ctrl=false
......@@ -485,7 +507,7 @@ class @CombinedOpenEnded
@errors_area.html(@out_of_sync_message)
confirm_reset: (event) =>
@reset(event) if confirm('Are you sure you want to remove your previous response to this question?')
@reset(event) if confirm(gettext 'Are you sure you want to remove your previous response to this question?')
reset: (event) =>
event.preventDefault()
......@@ -522,9 +544,14 @@ class @CombinedOpenEnded
@rebind()
@next_problem_button.hide()
if !response.allow_reset
@gentle_alert "Moved to next step."
@gentle_alert gettext "Moved to next step."
else
@gentle_alert "Your score did not meet the criteria to move to the next step."
###
Translators: this message appears when transitioning between openended grading
types (i.e. self assesment to peer assessment). Sometimes, if a student
did not perform well at one step, they cannot move on to the next one.
###
@gentle_alert gettext "Your score did not meet the criteria to move to the next step."
@show_combined_rubric_current()
else
@errors_area.html(response.error)
......@@ -561,7 +588,7 @@ class @CombinedOpenEnded
@$(@file_upload_preview_sel).hide()
@$(@file_upload_box_sel).change @preview_image
else
@gentle_alert 'File uploads are required for this question, but are not supported in this browser. Try the newest version of google chrome. Alternatively, if you have uploaded the image to the web, you can paste a link to it into the answer box.'
@gentle_alert gettext 'File uploads are required for this question, but are not supported in your browser. Try the newest version of Google Chrome. Alternatively, if you have uploaded the image to another website, you can paste a link to it into the answer box.'
hide_file_upload: =>
if @accept_file_upload == "True"
......@@ -582,12 +609,20 @@ class @CombinedOpenEnded
collapse_question: (event) =>
@prompt_container.slideToggle()
@prompt_container.toggleClass('open')
if @question_header.text() == "Hide Question"
new_text = "Show Question"
Logger.log 'oe_hide_question', {location: @location}
else
if @prompt_container.hasClass('open')
###
Translators: "Show Question" is some text that, when clicked, shows a question's
content that had been hidden
###
new_text = gettext "Show Question"
Logger.log 'oe_show_question', {location: @location}
new_text = "Hide Question"
else
###
Translators: "Hide Question" is some text that, when clicked, hides a question's
content
###
Logger.log 'oe_hide_question', {location: @location}
new_text = gettext "Hide Question"
@question_header.text(new_text)
return false
......@@ -627,19 +662,19 @@ class @CombinedOpenEnded
if @prompt_container.is(":hidden")==true
@prompt_container.slideToggle()
@prompt_container.toggleClass('open')
@question_header.text("Hide Question")
@question_header.text(gettext "Hide Question")
prompt_hide: () =>
if @prompt_container.is(":visible")==true
@prompt_container.slideToggle()
@prompt_container.toggleClass('open')
@question_header.text("Show Question")
@question_header.text(gettext "Show Question")
log_feedback_click: (event) ->
link_text = @$(event.target).html()
if link_text == 'See full feedback'
target = @$(event.target)
if target.hasClass('see-full-feedback')
Logger.log 'oe_show_full_feedback', {}
else if link_text == 'Respond to Feedback'
else if target.hasClass('respond-to-feedback')
Logger.log 'oe_show_respond_to_feedback', {}
else
generated_event_type = link_text.toLowerCase().replace(" ","_")
......
......@@ -34,18 +34,31 @@ ACCEPT_FILE_UPLOAD = False
# Contains all reasonable bool and case combinations of True
TRUE_DICT = ["True", True, "TRUE", "true"]
_ = lambda text: text
HUMAN_TASK_TYPE = {
'selfassessment': "Self",
# Translators: "Self" is used to denote an openended response that is self-graded
'selfassessment': _("Self"),
'openended': "edX",
'ml_grading.conf': "AI",
'peer_grading.conf': "Peer",
# Translators: "AI" is used to denote an openended response that is machine-graded
'ml_grading.conf': _("AI"),
# Translators: "Peer" is used to denote an openended response that is peer-graded
'peer_grading.conf': _("Peer"),
}
HUMAN_STATES = {
'intitial': "Not started.",
'assessing': "Being scored.",
'intermediate_done': "Scoring finished.",
'done': "Complete.",
# Translators: "Not started" is used to communicate to a student that their response
# has not yet been graded
'intitial': _("Not started."),
# Translators: "Being scored." is used to communicate to a student that their response
# are in the process of being scored
'assessing': _("Being scored."),
# Translators: "Scoring finished" is used to communicate to a student that their response
# have been scored, but the full scoring process is not yet complete
'intermediate_done': _("Scoring finished."),
# Translators: "Complete" is used to communicate to a student that their
# openended response has been fully scored
'done': _("Complete."),
}
# Default value that controls whether or not to skip basic spelling checks in the controller
......@@ -86,6 +99,10 @@ class CombinedOpenEndedV1Module():
# Where the templates live for this problem
TEMPLATE_DIR = "combinedopenended"
# hack: included to make this class act enough like an xblock to get i18n
_services_requested = {"i18n": "need"}
_combined_services = _services_requested
def __init__(self, system, location, definition, descriptor,
instance_state=None, shared_state=None, metadata=None, static_data=None, **kwargs):
......@@ -541,6 +558,7 @@ class CombinedOpenEndedV1Module():
"""
task_html = self.get_html_base()
# set context variables and render template
ugettext = self.system.service(self, "i18n").ugettext
context = {
'items': [{'content': task_html}],
......@@ -549,12 +567,12 @@ class CombinedOpenEndedV1Module():
'state': self.state,
'task_count': len(self.task_xml),
'task_number': self.current_task_number + 1,
'status': self.get_status(False),
'status': ugettext(self.get_status(False)),
'display_name': self.display_name,
'accept_file_upload': self.accept_file_upload,
'location': self.location,
'legend_list': LEGEND_LIST,
'human_state': HUMAN_STATES.get(self.state, "Not started."),
'human_state': ugettext(HUMAN_STATES.get(self.state, "Not started.")),
'is_staff': self.system.user_is_staff,
}
......@@ -567,7 +585,9 @@ class CombinedOpenEndedV1Module():
Output: rendered html
"""
context = self.get_context()
html = self.system.render_template('{0}/combined_open_ended.html'.format(self.TEMPLATE_DIR), context)
html = self.system.render_template(
'{0}/combined_open_ended.html'.format(self.TEMPLATE_DIR), context
)
return html
def get_html_nonsystem(self):
......@@ -578,7 +598,9 @@ class CombinedOpenEndedV1Module():
Output: HTML rendered directly via Mako
"""
context = self.get_context()
html = self.system.render_template('{0}/combined_open_ended.html'.format(self.TEMPLATE_DIR), context)
html = self.system.render_template(
'{0}/combined_open_ended.html'.format(self.TEMPLATE_DIR), context
)
return html
def get_html_base(self):
......@@ -815,6 +837,7 @@ class CombinedOpenEndedV1Module():
Input: AJAX data dictionary
Output: Dictionary to be rendered via ajax that contains the result html.
"""
ugettext = self.system.service(self, "i18n").ugettext
all_responses = []
success, can_see_rubric, error = self.check_if_student_has_done_needed_grading()
if not can_see_rubric:
......@@ -841,12 +864,20 @@ class CombinedOpenEndedV1Module():
rubric_scores = [[response['rubric_scores'][z]]]
grader_types = [[response['grader_types'][z]]]
feedback_items = [[response['feedback_items'][z]]]
rubric_html = self.rubric_renderer.render_combined_rubric(stringify_children(self.static_data['rubric']),
rubric_html = self.rubric_renderer.render_combined_rubric(
stringify_children(self.static_data['rubric']),
rubric_scores,
grader_types, feedback_items)
grader_types,
feedback_items
)
contexts.append({
'result': rubric_html,
'task_name': 'Scored rubric',
# Translators: "Scored rubric" appears to a user as part of a longer
# string that looks something like: "Scored rubric from grader 1".
# "Scored" is an adjective that modifies the noun "rubric".
# That longer string appears when a user is viewing a graded rubric
# returned from one of the graders of their openended response problem.
'task_name': ugettext('Scored rubric'),
'feedback' : feedback
})
......@@ -925,6 +956,7 @@ class CombinedOpenEndedV1Module():
Input: AJAX data dictionary
Output: AJAX dictionary to tbe rendered
"""
ugettext = self.system.service(self, "i18n").ugettext
if self.state != self.DONE:
if not self.ready_to_reset:
return self.out_of_sync_error(data)
......@@ -937,10 +969,13 @@ class CombinedOpenEndedV1Module():
return {
'success': False,
# This is a student_facing_error
'error': (
'You have attempted this question {0} times. '
'You are only allowed to attempt it {1} times.'
).format(self.student_attempts, self.max_attempts)
'error': ugettext(
'You have attempted this question {number_of_student_attempts} times. '
'You are only allowed to attempt it {max_number_of_attempts} times.'
).format(
number_of_student_attempts=self.student_attempts,
max_number_of_attempts=self.max_attempts
)
}
self.student_attempts +=1
self.state = self.INITIAL
......@@ -980,26 +1015,32 @@ class CombinedOpenEndedV1Module():
Input: None
Output: The status html to be rendered
"""
status = []
ugettext = self.system.service(self, "i18n").ugettext
status_list = []
current_task_human_name = ""
for i in xrange(0, len(self.task_xml)):
human_task_name = self.extract_human_name_from_task(self.task_xml[i])
human_task_name = ugettext(human_task_name)
# Extract the name of the current task for screen readers.
if self.current_task_number == i:
current_task_human_name = human_task_name
task_data = {'task_number': i + 1, 'human_task': human_task_name, 'current': self.current_task_number==i}
status.append(task_data)
task_data = {
'task_number': i + 1,
'human_task': human_task_name,
'current': self.current_task_number == i
}
status_list.append(task_data)
context = {
'status_list': status,
'status_list': status_list,
'grader_type_image_dict': GRADER_TYPE_IMAGE_DICT,
'legend_list': LEGEND_LIST,
'render_via_ajax': render_via_ajax,
'current_task_human_name': current_task_human_name,
}
status_html = self.system.render_template("{0}/combined_open_ended_status.html".format(self.TEMPLATE_DIR),
context)
status_html = self.system.render_template(
"{0}/combined_open_ended_status.html".format(self.TEMPLATE_DIR), context
)
return status_html
......@@ -1109,12 +1150,39 @@ class CombinedOpenEndedV1Module():
"""
return dict out-of-sync error message, and also log.
"""
ugettext = self.system.service(self, "i18n").ugettext
#This is a dev_facing_error
log.warning("Combined module state out sync. state: %r, data: %r. %s",
self.state, data, msg)
log.warning(
"Combined module state out sync. state: %r, data: %r. %s",
self.state,
data,
msg
)
#This is a student_facing_error
return {'success': False,
'error': 'The problem state got out-of-sync. Please try reloading the page.'}
return {
'success': False,
'error': ugettext('The problem state got out-of-sync. Please try reloading the page.')
}
@classmethod
def service_declaration(cls, service_name):
"""
This classmethod is copied from XBlock's service_declaration.
It is included to make this class act enough like an XBlock
to get i18n working on it.
This is currently only used for i18n, and will return "need"
in that case.
Arguments:
service_name (string): the name of the service requested.
Returns:
One of "need", "want", or None.
"""
declaration = cls._combined_services.get(service_name)
return declaration
class CombinedOpenEndedV1Descriptor():
......
......@@ -11,12 +11,19 @@ GRADER_TYPE_IMAGE_DICT = {
'BC': '/static/images/ml_grading_icon.png',
}
_ = lambda text: text
HUMAN_GRADER_TYPE = {
'SA': 'Self-Assessment',
'PE': 'Peer-Assessment',
'IN': 'Instructor-Assessment',
'ML': 'AI-Assessment',
'BC': 'AI-Assessment',
# Translators: "Self-Assessment" refers to the self-assessed mode of openended evaluation
'SA': _('Self-Assessment'),
# Translators: "Peer-Assessment" refers to the peer-assessed mode of openended evaluation
'PE': _('Peer-Assessment'),
# Translators: "Instructor-Assessment" refers to the instructor-assessed mode of openended evaluation
'IN': _('Instructor-Assessment'),
# Translators: "AI-Assessment" refers to the machine-graded mode of openended evaluation
'ML': _('AI-Assessment'),
# Translators: "AI-Assessment" refers to the machine-graded mode of openended evaluation
'BC': _('AI-Assessment'),
}
DO_NOT_DISPLAY = ['BC', 'IN']
......@@ -63,13 +70,16 @@ class CombinedOpenEndedRubric(object):
rubric_template = '{0}/open_ended_rubric.html'.format(self.TEMPLATE_DIR)
if self.view_only:
rubric_template = '{0}/open_ended_view_only_rubric.html'.format(self.TEMPLATE_DIR)
html = self.system.render_template(rubric_template,
{'categories': rubric_categories,
html = self.system.render_template(
rubric_template,
{
'categories': rubric_categories,
'has_score': self.has_score,
'view_only': self.view_only,
'max_score': max_score,
'combined_rubric': False
})
'combined_rubric': False,
}
)
success = True
except:
#This is a staff_facing_error
......@@ -153,7 +163,6 @@ class CombinedOpenEndedRubric(object):
"[extract_category] Category {0} is missing a score. Contact the learning sciences group for assistance.".format(
descriptionxml.text))
# parse description
if descriptionxml.tag != 'description':
#This is a staff_facing_error
......@@ -245,17 +254,20 @@ class CombinedOpenEndedRubric(object):
else:
correct.append(.5)
html = self.system.render_template('{0}/open_ended_combined_rubric.html'.format(self.TEMPLATE_DIR),
{'categories': rubric_categories,
html = self.system.render_template(
'{0}/open_ended_combined_rubric.html'.format(self.TEMPLATE_DIR),
{
'categories': rubric_categories,
'max_scores': max_scores,
'correct' : correct,
'correct': correct,
'has_score': True,
'view_only': True,
'max_score': max_score,
'combined_rubric': True,
'grader_type_image_dict': GRADER_TYPE_IMAGE_DICT,
'human_grader_types': HUMAN_GRADER_TYPE,
})
}
)
return html
@staticmethod
......
......@@ -149,14 +149,22 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
event_info['problem_id'] = self.location_string
event_info['student_id'] = system.anonymous_student_id
event_info['survey_responses'] = data
_ = self.system.service(self, "i18n").ugettext
survey_responses = event_info['survey_responses']
for tag in ['feedback', 'submission_id', 'grader_id', 'score']:
if tag not in survey_responses:
# This is a student_facing_error
return {'success': False,
'msg': "Could not find needed tag {0} in the survey responses. Please try submitting again.".format(
tag)}
return {
'success': False,
# Translators: 'tag' is one of 'feedback', 'submission_id',
# 'grader_id', or 'score'. They are categories that a student
# responds to when filling out a post-assessment survey
# of his or her grade from an openended problem.
'msg': _("Could not find needed tag {tag_name} in the "
"survey responses. Please try submitting "
"again.").format(tag_name=tag)
}
try:
submission_id = int(survey_responses['submission_id'])
grader_id = int(survey_responses['grader_id'])
......@@ -171,11 +179,17 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
)
log.exception(error_message)
# This is a student_facing_error
return {'success': False, 'msg': "There was an error saving your feedback. Please contact course staff."}
return {
'success': False,
'msg': _(
"There was an error saving your feedback. Please "
"contact course staff."
)
}
xqueue = system.get('xqueue')
if xqueue is None:
return {'success': False, 'msg': "Couldn't submit feedback."}
return {'success': False, 'msg': _("Couldn't submit feedback.")}
qinterface = xqueue['interface']
qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat)
anonymous_student_id = system.anonymous_student_id
......@@ -208,10 +222,10 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
# Convert error to a success value
success = True
message = "Successfully saved your feedback."
message = _("Successfully saved your feedback.")
if error:
success = False
message = "Unable to save your feedback. Please try again later."
message = _("Unable to save your feedback. Please try again later.")
log.error("Unable to send feedback to grader. location: {0}, error_message: {1}".format(
self.location_string, error_message
))
......@@ -277,12 +291,14 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
'key': queuekey,
'time': qtime,
}
_ = self.system.service(self, "i18n").ugettext
success = True
message = "Successfully saved your submission."
message = _("Successfully saved your submission.")
if error:
success = False
message = 'Unable to submit your submission to grader. Please try again later.'
# Translators: the `grader` refers to the grading service open response problems
# are sent to, either to be machine-graded, peer-graded, or instructor-graded.
message = _('Unable to submit your submission to the grader. Please try again later.')
log.error("Unable to submit to grader. location: {0}, error_message: {1}".format(
self.location_string, error_message
))
......@@ -297,9 +313,12 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
@param system: Modulesystem
@return: Boolean True (not useful currently)
"""
_ = self.system.service(self, "i18n").ugettext
new_score_msg = self._parse_score_msg(score_msg, system)
if not new_score_msg['valid']:
new_score_msg['feedback'] = 'Invalid grader reply. Please contact the course staff.'
# Translators: the `grader` refers to the grading service open response problems
# are sent to, either to be machine-graded, peer-graded, or instructor-graded.
new_score_msg['feedback'] = _('Invalid grader reply. Please contact the course staff.')
# self.child_history is initialized as []. record_latest_score() and record_latest_post_assessment()
# operate on self.child_history[-1]. Thus we have to make sure child_history is not [].
......@@ -387,7 +406,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
def format_feedback(feedback_type, value):
feedback_type, value = encode_values(feedback_type, value)
feedback = """
feedback = u"""
<div class="{feedback_type}">
{value}
</div>
......@@ -405,10 +424,15 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
# that we can do proper escaping here (e.g. are the graders allowed to
# include HTML?)
_ = self.system.service(self, "i18n").ugettext
for tag in ['success', 'feedback', 'submission_id', 'grader_id']:
if tag not in response_items:
# This is a student_facing_error
return format_feedback('errors', 'Error getting feedback from grader.')
return format_feedback(
# Translators: the `grader` refers to the grading service open response problems
# are sent to, either to be machine-graded, peer-graded, or instructor-graded.
'errors', _('Error getting feedback from grader.')
)
feedback_items = response_items['feedback']
try:
......@@ -417,12 +441,20 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
# This is a dev_facing_error
log.exception("feedback_items from external open ended grader have invalid json {0}".format(feedback_items))
# This is a student_facing_error
return format_feedback('errors', 'Error getting feedback from grader.')
return format_feedback(
# Translators: the `grader` refers to the grading service open response problems
# are sent to, either to be machine-graded, peer-graded, or instructor-graded.
'errors', _('Error getting feedback from grader.')
)
if response_items['success']:
if len(feedback) == 0:
# This is a student_facing_error
return format_feedback('errors', 'No feedback available from grader.')
return format_feedback(
# Translators: the `grader` refers to the grading service open response problems
# are sent to, either to be machine-graded, peer-graded, or instructor-graded.
'errors', _('No feedback available from grader.')
)
for tag in do_not_render:
if tag in feedback:
......@@ -648,12 +680,14 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
'check_for_score': self.check_for_score,
'store_answer': self.store_answer,
}
_ = self.system.service(self, "i18n").ugettext
if dispatch not in handlers:
# This is a dev_facing_error
log.error("Cannot find {0} in handlers in handle_ajax function for open_ended_module.py".format(dispatch))
# This is a dev_facing_error
return json.dumps({'error': 'Error handling action. Please try again.', 'success': False})
return json.dumps(
{'error': _('Error handling action. Please try again.'), 'success': False}
)
before = self.get_progress()
d = handlers[dispatch](data, system)
......@@ -733,6 +767,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
Input: Modulesystem object
Output: Rendered HTML
"""
_ = self.system.service(self, "i18n").ugettext
# set context variables and render template
eta_string = None
if self.child_state != self.INITIAL:
......@@ -740,7 +775,9 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
score = self.latest_score()
correct = 'correct' if self.is_submission_correct(score) else 'incorrect'
if self.child_state == self.ASSESSING:
eta_string = "Your response has been submitted. Please check back later for your grade."
# Translators: this string appears once an openended response
# is submitted but before it has been graded
eta_string = _("Your response has been submitted. Please check back later for your grade.")
else:
post_assessment = ""
correct = ""
......
......@@ -25,9 +25,6 @@ MAX_ATTEMPTS = 1
# Overriden by max_score specified in xml.
MAX_SCORE = 1
FILE_NOT_FOUND_IN_RESPONSE_MESSAGE = "We could not find a file in your submission. Please try choosing a file or pasting a link to your file into the answer box."
ERROR_SAVING_FILE_MESSAGE = "We are having trouble saving your file. Please try another file or paste a link to your file into the answer box."
def upload_to_s3(file_to_upload, keyname, s3_interface):
'''
......@@ -91,13 +88,24 @@ class OpenEndedChild(object):
DONE = 'done'
# This is used to tell students where they are at in the module
_ = lambda text: text
HUMAN_NAMES = {
'initial': 'Not started',
'assessing': 'In progress',
'post_assessment': 'Done',
'done': 'Done',
# Translators: "Not started" communicates to a student that their response
# has not yet been graded
'initial': _('Not started'),
# Translators: "In progress" communicates to a student that their response
# is currently in the grading process
'assessing': _('In progress'),
# Translators: "Done" communicates to a student that their response
# has been fully graded
'post_assessment': _('Done'),
'done': _('Done'),
}
# included to make this act enough like an xblock to get i18n
_services_requested = {"i18n": "need"}
_combined_services = _services_requested
def __init__(self, system, location, definition, descriptor, static_data,
instance_state=None, shared_state=None, **kwargs):
# Load instance state
......@@ -463,6 +471,8 @@ class OpenEndedChild(object):
@return: Boolean success, and updated AJAX data dictionary.
"""
_ = self.system.service(self, "i18n").ugettext
error_message = ""
if not self.accept_file_upload:
......@@ -481,7 +491,11 @@ class OpenEndedChild(object):
# If success is False, we have not found a link, and no file was attached.
# Show error to student.
if success is False:
error_message = FILE_NOT_FOUND_IN_RESPONSE_MESSAGE
error_message = _(
"We could not find a file in your submission. "
"Please try choosing a file or pasting a URL to your "
"file into the answer box."
)
except Exception:
# In this case, an image was submitted by the student, but the image could not be uploaded to S3. Likely
......@@ -490,7 +504,10 @@ class OpenEndedChild(object):
"but the image was not able to be uploaded to S3. This could indicate a configuration "
"issue with this deployment and the S3_INTERFACE setting.")
success = False
error_message = ERROR_SAVING_FILE_MESSAGE
error_message = _(
"We are having trouble saving your file. Please try another "
"file or paste a URL to your file into the answer box."
)
return success, error_message, data
......@@ -534,3 +551,23 @@ class OpenEndedChild(object):
eta_string = ""
return eta_string
@classmethod
def service_declaration(cls, service_name):
"""
This classmethod is copied from XBlock's service_declaration.
It is included to make this class act enough like an XBlock
to get i18n working on it.
This is currently only used for i18n, and will return "need"
in that case.
Arguments:
service_name (string): the name of the service requested.
Returns:
One of "need", "want", or None.
"""
declaration = cls._combined_services.get(service_name)
return declaration
......@@ -125,7 +125,8 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
rubric_html = rubric_dict['html']
# we'll render it
context = {'rubric': rubric_html,
context = {
'rubric': rubric_html,
'max_score': self._max_score,
}
......@@ -233,7 +234,11 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
# This is a dev_facing_error
log.error("Non-integer score value passed to save_assessment, or no score list present.")
# This is a student_facing_error
return {'success': False, 'error': "Error saving your score. Please notify course staff."}
_ = self.system.service(self, "i18n").ugettext
return {
'success': False,
'error': _("Error saving your score. Please notify course staff.")
}
# Record score as assessment and rubric scores as post assessment
self.record_latest_score(score)
......@@ -266,9 +271,11 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
self.record_latest_post_assessment(data['hint'])
self.change_state(self.DONE)
return {'success': True,
return {
'success': True,
'message_html': '',
'allow_reset': self._allow_reset()}
'allow_reset': self._allow_reset(),
}
def latest_post_assessment(self, system):
latest_post_assessment = super(SelfAssessmentModule, self).latest_post_assessment(system)
......
......@@ -55,7 +55,7 @@ class RubricPage(PageObject):
num_categories = self.categories
if len(scores) != len(num_categories):
raise ScoreMismatchError(
"Recieved {0} scores but there are {1} rubric categories".format(
"Received {0} scores but there are {1} rubric categories".format(
len(scores), num_categories))
# Set the score for each category
......
......@@ -37,7 +37,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2014-02-11 18:20-0500\n"
"POT-Creation-Date: 2014-02-14 16:00-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
......@@ -507,7 +507,12 @@ msgstr ""
"trý ägäïn lätér. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
#. Translators: 'grader' refers to the edX automatic code grader.
#. Translators: the `grader` refers to the grading service open response
#. problems
#. are sent to, either to be machine-graded, peer-graded, or instructor-
#. graded.
#: common/lib/capa/capa/responsetypes.py
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid "Invalid grader reply. Please contact the course staff."
msgstr ""
"Ìnvälïd grädér réplý. Pléäsé çöntäçt thé çöürsé stäff. Ⱡ'σяєм ιρѕυм ∂σ#"
......@@ -673,6 +678,219 @@ msgstr ""
"À ÝöüTüßé ÛRL ör ä lïnk tö ä fïlé höstéd änýwhéré ön thé wéß. Ⱡ'σяєм ιρѕυм "
"∂σłσя#"
#. Translators: "Self" is used to denote an openended response that is self-
#. graded
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
msgid "Self"
msgstr "Sélf Ⱡ'σяєм#"
#. Translators: "AI" is used to denote an openended response that is machine-
#. graded
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
msgid "AI"
msgstr "ÀÌ Ⱡ'#"
#. Translators: "Peer" is used to denote an openended response that is peer-
#. graded
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
msgid "Peer"
msgstr "Péér Ⱡ'σяєм#"
#. Translators: "Not started" is used to communicate to a student that their
#. response
#. has not yet been graded
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
msgid "Not started."
msgstr "Nöt stärtéd. Ⱡ#"
#. Translators: "Being scored." is used to communicate to a student that their
#. response
#. are in the process of being scored
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
msgid "Being scored."
msgstr "Béïng sçöréd. Ⱡ'#"
#. Translators: "Scoring finished" is used to communicate to a student that
#. their response
#. have been scored, but the full scoring process is not yet complete
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
msgid "Scoring finished."
msgstr "Sçörïng fïnïshéd. Ⱡ'σ#"
#. Translators: "Complete" is used to communicate to a student that their
#. openended response has been fully scored
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
msgid "Complete."
msgstr "Çömplété. #"
#. Translators: "Scored rubric" appears to a user as part of a longer
#. string that looks something like: "Scored rubric from grader 1".
#. "Scored" is an adjective that modifies the noun "rubric".
#. That longer string appears when a user is viewing a graded rubric
#. returned from one of the graders of their openended response problem.
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
msgid "Scored rubric"
msgstr "Sçöréd rüßrïç Ⱡ'#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
#, python-brace-format
msgid ""
"You have attempted this question {number_of_student_attempts} times. You are"
" only allowed to attempt it {max_number_of_attempts} times."
msgstr ""
"Ýöü hävé ättémptéd thïs qüéstïön {number_of_student_attempts} tïmés. Ýöü äré"
" önlý ällöwéd tö ättémpt ït {max_number_of_attempts} tïmés. Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
msgid "The problem state got out-of-sync. Please try reloading the page."
msgstr ""
"Thé prößlém stäté göt öüt-öf-sýnç. Pléäsé trý rélöädïng thé pägé. Ⱡ'σяєм "
"ιρѕυм ∂σłσя #"
#. Translators: "Self-Assessment" refers to the self-assessed mode of
#. openended evaluation
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_rubric.py
msgid "Self-Assessment"
msgstr "Sélf-Àsséssmént Ⱡ'#"
#. Translators: "Peer-Assessment" refers to the peer-assessed mode of
#. openended evaluation
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_rubric.py
msgid "Peer-Assessment"
msgstr "Péér-Àsséssmént Ⱡ'#"
#. Translators: "Instructor-Assessment" refers to the instructor-assessed mode
#. of openended evaluation
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_rubric.py
msgid "Instructor-Assessment"
msgstr "Ìnstrüçtör-Àsséssmént Ⱡ'σя#"
#. Translators: "AI-Assessment" refers to the machine-graded mode of openended
#. evaluation
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_rubric.py
#: common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_rubric.py
msgid "AI-Assessment"
msgstr "ÀÌ-Àsséssmént Ⱡ'#"
#. Translators: 'tag' is one of 'feedback', 'submission_id',
#. 'grader_id', or 'score'. They are categories that a student
#. responds to when filling out a post-assessment survey
#. of his or her grade from an openended problem.
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
#, python-brace-format
msgid ""
"Could not find needed tag {tag_name} in the survey responses. Please try "
"submitting again."
msgstr ""
"Çöüld nöt fïnd néédéd täg {tag_name} ïn thé sürvéý réspönsés. Pléäsé trý "
"süßmïttïng ägäïn. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid "There was an error saving your feedback. Please contact course staff."
msgstr ""
"Théré wäs än érrör sävïng ýöür féédßäçk. Pléäsé çöntäçt çöürsé stäff. Ⱡ'σяєм"
" ιρѕυм ∂σłσя ѕ#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid "Couldn't submit feedback."
msgstr "Çöüldn't süßmït féédßäçk. Ⱡ'σяєм#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid "Successfully saved your feedback."
msgstr "Süççéssfüllý sävéd ýöür féédßäçk. Ⱡ'σяєм ι#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid "Unable to save your feedback. Please try again later."
msgstr ""
"Ûnäßlé tö sävé ýöür féédßäçk. Pléäsé trý ägäïn lätér. Ⱡ'σяєм ιρѕυм ∂σ#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid "Successfully saved your submission."
msgstr "Süççéssfüllý sävéd ýöür süßmïssïön. Ⱡ'σяєм ιρ#"
#. Translators: the `grader` refers to the grading service open response
#. problems
#. are sent to, either to be machine-graded, peer-graded, or instructor-
#. graded.
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid ""
"Unable to submit your submission to the grader. Please try again later."
msgstr ""
"Ûnäßlé tö süßmït ýöür süßmïssïön tö thé grädér. Pléäsé trý ägäïn lätér. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
#. Translators: the `grader` refers to the grading service open response
#. problems
#. are sent to, either to be machine-graded, peer-graded, or instructor-
#. graded.
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid "Error getting feedback from grader."
msgstr "Érrör géttïng féédßäçk fröm grädér. Ⱡ'σяєм ιρ#"
#. Translators: the `grader` refers to the grading service open response
#. problems
#. are sent to, either to be machine-graded, peer-graded, or instructor-
#. graded.
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid "No feedback available from grader."
msgstr "Nö féédßäçk äväïläßlé fröm grädér. Ⱡ'σяєм ιρ#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid "Error handling action. Please try again."
msgstr "Érrör händlïng äçtïön. Pléäsé trý ägäïn. Ⱡ'σяєм ιρѕυ#"
#. Translators: this string appears once an openended response
#. is submitted but before it has been graded
#: common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
msgid ""
"Your response has been submitted. Please check back later for your grade."
msgstr ""
"Ýöür réspönsé häs ßéén süßmïttéd. Pléäsé çhéçk ßäçk lätér för ýöür grädé. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#"
#. Translators: "Not started" communicates to a student that their response
#. has not yet been graded
#: common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py
msgid "Not started"
msgstr "Nöt stärtéd Ⱡ#"
#. Translators: "In progress" communicates to a student that their response
#. is currently in the grading process
#: common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py
msgid "In progress"
msgstr "Ìn prögréss Ⱡ#"
#. Translators: "Done" communicates to a student that their response
#. has been fully graded
#: common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py
#: common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py
msgid "Done"
msgstr "Döné Ⱡ'σяєм#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py
msgid ""
"We could not find a file in your submission. Please try choosing a file or "
"pasting a URL to your file into the answer box."
msgstr ""
"Wé çöüld nöt fïnd ä fïlé ïn ýöür süßmïssïön. Pléäsé trý çhöösïng ä fïlé ör "
"pästïng ä ÛRL tö ýöür fïlé ïntö thé änswér ßöx. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт,"
" ¢σηѕє¢тєт#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py
msgid ""
"We are having trouble saving your file. Please try another file or paste a "
"URL to your file into the answer box."
msgstr ""
"Wé äré hävïng tröüßlé sävïng ýöür fïlé. Pléäsé trý änöthér fïlé ör pästé ä "
"ÛRL tö ýöür fïlé ïntö thé änswér ßöx. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#"
#: common/lib/xmodule/xmodule/open_ended_grading_classes/self_assessment_module.py
msgid "Error saving your score. Please notify course staff."
msgstr ""
"Érrör sävïng ýöür sçöré. Pléäsé nötïfý çöürsé stäff. Ⱡ'σяєм ιρѕυм ∂σ#"
#: common/static/js/vendor/mathjax-MathJax-c9db6ac/docs/source/mjtheme/layout.html
msgid "Navigation"
msgstr "Nävïgätïön Ⱡ#"
......@@ -1025,6 +1243,18 @@ msgstr "Çlösé thréäd Ⱡ#"
#: lms/djangoapps/django_comment_client/base/views.py
#: lms/djangoapps/django_comment_client/base/views.py
msgid "Title can't be empty"
msgstr "Tïtlé çän't ßé émptý Ⱡ'σя#"
#: lms/djangoapps/django_comment_client/base/views.py
#: lms/djangoapps/django_comment_client/base/views.py
#: lms/djangoapps/django_comment_client/base/views.py
#: lms/djangoapps/django_comment_client/base/views.py
msgid "Body can't be empty"
msgstr "Bödý çän't ßé émptý Ⱡ'σя#"
#: lms/djangoapps/django_comment_client/base/views.py
#: lms/djangoapps/django_comment_client/base/views.py
msgid "Comment level too deep"
msgstr "Çömmént lévél töö déép Ⱡ'σяє#"
......@@ -2775,6 +3005,89 @@ msgstr "révïsïöns #"
msgid "There are no attachments for this article."
msgstr "Théré äré nö ättäçhménts för thïs ärtïçlé. Ⱡ'σяєм ιρѕυ#"
#: cms/djangoapps/contentstore/git_export_utils.py
#, python-brace-format
msgid ""
"GIT_REPO_EXPORT_DIR not set or path {0} doesn't exist, please create it, or "
"configure a different path with GIT_REPO_EXPORT_DIR"
msgstr ""
"GÌT_RÉPÖ_ÉXPÖRT_DÌR nöt sét ör päth {0} döésn't éxïst, pléäsé çréäté ït, ör "
"çönfïgüré ä dïfférént päth wïth GÌT_RÉPÖ_ÉXPÖRT_DÌR Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυ#"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid ""
"Non writable git url provided. Expecting something like: "
"git@github.com:mitocw/edx4edx_lite.git"
msgstr ""
"Nön wrïtäßlé gït ürl prövïdéd. Éxpéçtïng söméthïng lïké: "
"gït@gïthüß.çöm:mïtöçw/édx4édx_lïté.gït Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid ""
"If using http urls, you must provide the username and password in the url. "
"Similar to https://user:pass@github.com/user/course."
msgstr ""
"Ìf üsïng http ürls, ýöü müst prövïdé thé üsérnämé änd pässwörd ïn thé ürl. "
"Sïmïlär tö https://üsér:päss@gïthüß.çöm/üsér/çöürsé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυ#"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid "Unable to determine branch, repo in detached HEAD mode"
msgstr ""
"Ûnäßlé tö détérmïné ßränçh, répö ïn détäçhéd HÉÀD mödé Ⱡ'σяєм ιρѕυм ∂σ#"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid "Unable to update or clone git repository."
msgstr "Ûnäßlé tö üpdäté ör çlöné gït répösïtörý. Ⱡ'σяєм ιρѕυ#"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid "Unable to export course to xml."
msgstr "Ûnäßlé tö éxpört çöürsé tö xml. Ⱡ'σяєм ι#"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid "Unable to configure git username and password"
msgstr "Ûnäßlé tö çönfïgüré gït üsérnämé änd pässwörd Ⱡ'σяєм ιρѕυм#"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid ""
"Unable to commit changes. This is usually because there are no changes to be"
" committed"
msgstr ""
"Ûnäßlé tö çömmït çhängés. Thïs ïs üsüällý ßéçäüsé théré äré nö çhängés tö ßé"
" çömmïttéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid ""
"Unable to push changes. This is usually because the remote repository "
"cannot be contacted"
msgstr ""
"Ûnäßlé tö püsh çhängés. Thïs ïs üsüällý ßéçäüsé thé rémöté répösïtörý "
"çännöt ßé çöntäçtéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid "Bad course location provided"
msgstr "Bäd çöürsé löçätïön prövïdéd Ⱡ'σяєм #"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid "Missing branch on fresh clone"
msgstr "Mïssïng ßränçh ön frésh çlöné Ⱡ'σяєм #"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid "Command was: {0!r}. Working directory was: {1!r}"
msgstr "Çömmänd wäs: {0!r}. Wörkïng dïréçtörý wäs: {1!r} Ⱡ'σяєм ιρѕυм#"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid "Command output was: {0!r}"
msgstr "Çömmänd öütpüt wäs: {0!r} Ⱡ'σяє#"
#: cms/djangoapps/contentstore/git_export_utils.py
msgid ""
"Directory already exists, doing a git reset and pull instead of git clone."
msgstr ""
"Dïréçtörý älréädý éxïsts, döïng ä gït rését änd püll ïnstéäd öf gït çlöné. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#"
#: cms/djangoapps/contentstore/transcripts_utils.py
#, python-brace-format
msgid ""
......@@ -2815,6 +3128,14 @@ msgstr "Öpén Éndéd Pänél Ⱡ'σ#"
msgid "My Notes"
msgstr "Mý Nötés #"
#: cms/djangoapps/contentstore/management/commands/git_export.py
msgid ""
"Take the specified course and attempt to export it to a git repository\n"
". Course directory must already be a git repository. Usage: git_export <course_loc> <git_url>"
msgstr ""
"Täké thé spéçïfïéd çöürsé änd ättémpt tö éxpört ït tö ä gït répösïtörý\n"
". Çöürsé dïréçtörý müst älréädý ßé ä gït répösïtörý. Ûsägé: gït_éxpört <course_loc> <git_url> Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕ#"
#: cms/djangoapps/contentstore/views/assets.py
msgid "Upload completed"
msgstr "Ûplöäd çömplétéd Ⱡ'σ#"
......@@ -2859,6 +3180,10 @@ msgstr ""
"nümßér. Pléäsé çhängé ät léäst öné fïéld tö ßé ünïqüé. Ⱡ'σяєм ιρѕυм ∂σłσя "
"ѕιт αмєт, ¢σηѕє¢тєтυ#"
#: cms/djangoapps/contentstore/views/export_git.py
msgid "Course successfully exported to git repository"
msgstr "Çöürsé süççéssfüllý éxpörtéd tö gït répösïtörý Ⱡ'σяєм ιρѕυм #"
#: cms/djangoapps/contentstore/views/import_export.py
msgid "We only support uploading a .tar.gz file."
msgstr "Wé önlý süppört üplöädïng ä .tär.gz fïlé. Ⱡ'σяєм ιρѕυ#"
......@@ -5032,10 +5357,32 @@ msgstr "Süßmïttéd Rüßrïç Ⱡ'σ#"
msgid "Toggle Full Rubric"
msgstr "Tögglé Füll Rüßrïç Ⱡ'σ#"
#. Translators: an example of what this string will look
#. like is: "Scored rubric from grader 1", where
#. "Scored rubric" replaces {result_of_task} and
#. "1" replaces {number}.
#. This string appears when a user is viewing one of
#. their graded rubrics for an openended response problem.
#. the number distinguishes between the different
#. graded rubrics the user might have received
#: lms/templates/combinedopenended/combined_open_ended_results.html
msgid "{result_of_task} from grader {number}"
msgstr "{result_of_task} fröm grädér {number} Ⱡ'σя#"
#. Translators: "See full feedback" is the text of
#. a link that allows a user to see more detailed
#. feedback from a self, peer, or instructor
#. graded openended problem
#: lms/templates/combinedopenended/open_ended_result_table.html
msgid "See full feedback"
msgstr "Séé füll féédßäçk Ⱡ'σ#"
#. Translators: this text forms a link that, when
#. clicked, allows a user to respond to the feedback
#. the user received on his or her openended problem
#. Translators: when "Respond to Feedback" is clicked, a survey
#. appears on which a user can respond to the feedback the user
#. received on an openended problem
#: lms/templates/combinedopenended/open_ended_result_table.html
#: lms/templates/combinedopenended/openended/open_ended_evaluation.html
msgid "Respond to Feedback"
......@@ -5081,6 +5428,16 @@ msgstr "Àddïtïönäl çömménts: Ⱡ'σя#"
msgid "Submit Feedback"
msgstr "Süßmït Féédßäçk Ⱡ'#"
#. Translators: "Response" labels an area that contains the user's
#. Response to an openended problem. It is a noun.
#. Translators: "Response" labels a text area into which a user enters
#. his or her response to a prompt from an openended problem.
#: lms/templates/combinedopenended/openended/open_ended.html
#: lms/templates/combinedopenended/selfassessment/self_assessment_prompt.html
#: lms/templates/open_ended_problems/open_ended_flagged_problems.html
msgid "Response"
msgstr "Réspönsé #"
#: lms/templates/combinedopenended/openended/open_ended.html
msgid "Unanswered"
msgstr "Ûnänswéréd Ⱡ#"
......@@ -7323,10 +7680,6 @@ msgid "No flagged problems exist."
msgstr "Nö fläggéd prößléms éxïst. Ⱡ'σяєм#"
#: lms/templates/open_ended_problems/open_ended_flagged_problems.html
msgid "Response"
msgstr "Réspönsé #"
#: lms/templates/open_ended_problems/open_ended_flagged_problems.html
msgid "Unflag"
msgstr "Ûnfläg Ⱡ'σяєм ιρѕ#"
......@@ -9190,7 +9543,8 @@ msgid "close alert"
msgstr "çlösé älért Ⱡ#"
#: cms/templates/checklists.html cms/templates/export.html
#: cms/templates/import.html cms/templates/widgets/header.html
#: cms/templates/export_git.html cms/templates/import.html
#: cms/templates/widgets/header.html
msgid "Tools"
msgstr "Tööls Ⱡ'σяєм ι#"
......@@ -9570,6 +9924,62 @@ msgstr ""
"dätä ïnçlüdés thé çöürsé.xml fïlé, äs wéll äs süßföldérs thät çöntäïn çöürsé"
" çöntént. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιη#"
#: cms/templates/export_git.html
msgid "Export Course to Git"
msgstr "Éxpört Çöürsé tö Gït Ⱡ'σя#"
#: cms/templates/export_git.html cms/templates/export_git.html
#: cms/templates/widgets/header.html
msgid "Export to Git"
msgstr "Éxpört tö Gït Ⱡ'#"
#: cms/templates/export_git.html
msgid "About Export to Git"
msgstr "Àßöüt Éxpört tö Gït Ⱡ'σя#"
#: cms/templates/export_git.html
msgid "Use this to export your course to its git repository."
msgstr ""
"Ûsé thïs tö éxpört ýöür çöürsé tö ïts gït répösïtörý. Ⱡ'σяєм ιρѕυм ∂σ#"
#: cms/templates/export_git.html
msgid ""
"This will then trigger an automatic update of the main LMS site and update "
"the contents of your course visible there to students if automatic git "
"imports are configured."
msgstr ""
"Thïs wïll thén trïggér än äütömätïç üpdäté öf thé mäïn LMS sïté änd üpdäté "
"thé çönténts öf ýöür çöürsé vïsïßlé théré tö stüdénts ïf äütömätïç gït "
"ïmpörts äré çönfïgüréd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg"
" #"
#: cms/templates/export_git.html
msgid "Export Course to Git:"
msgstr "Éxpört Çöürsé tö Gït: Ⱡ'σя#"
#: cms/templates/export_git.html
msgid ""
"giturl must be defined in your course settings before you can export to git."
msgstr ""
"gïtürl müst ßé défïnéd ïn ýöür çöürsé séttïngs ßéföré ýöü çän éxpört tö gït."
" Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт #"
#: cms/templates/export_git.html
msgid "Export Failed"
msgstr "Éxpört Fäïléd Ⱡ'#"
#: cms/templates/export_git.html
msgid "Export Succeeded"
msgstr "Éxpört Süççéédéd Ⱡ'σ#"
#: cms/templates/export_git.html
msgid "Your course:"
msgstr "Ýöür çöürsé: Ⱡ#"
#: cms/templates/export_git.html
msgid "Course git url:"
msgstr "Çöürsé gït ürl: Ⱡ'#"
#: cms/templates/howitworks.html
msgid "Welcome"
msgstr "Wélçömé #"
......@@ -10853,6 +11263,18 @@ msgid "Information for prospective students"
msgstr "Ìnförmätïön för pröspéçtïvé stüdénts Ⱡ'σяєм ιρ#"
#: cms/templates/settings.html
msgid "Course Short Description"
msgstr "Çöürsé Shört Désçrïptïön Ⱡ'σяє#"
#: cms/templates/settings.html
msgid ""
"Appears on the course catalog page when students roll over the course name. "
"Limit to ~150 characters"
msgstr ""
"Àppéärs ön thé çöürsé çätälög pägé whén stüdénts röll övér thé çöürsé nämé. "
"Lïmït tö ~150 çhäräçtérs Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#"
#: cms/templates/settings.html
msgid "Course Overview"
msgstr "Çöürsé Övérvïéw Ⱡ'#"
......@@ -11153,7 +11575,7 @@ msgstr ""
" téxt äs ä sïnglé çhäptér änd éntér ä nämé öf ýöür çhöïçé ïn thé Çhäptér "
"Nämé fïéld. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ι#"
#: cms/templates/unit.html
#: cms/templates/unit.html cms/templates/ux/reference/unit.html
msgid "Individual Unit"
msgstr "Ìndïvïdüäl Ûnït Ⱡ'#"
......@@ -11325,6 +11747,10 @@ msgstr ""
"Àn äçtïvätïön lïnk häs ßéén sént tö {email}, älöng wïth ïnstrüçtïöns för "
"äçtïvätïng ýöür äççöünt. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт,#"
#: cms/templates/ux/reference/container.html
msgid "Container"
msgstr "Çöntäïnér #"
#: cms/templates/widgets/footer.html
msgid "All rights reserved."
msgstr "Àll rïghts résérvéd. Ⱡ'σя#"
......@@ -11450,6 +11876,10 @@ msgstr "Àdvänçéd Édïtör Ⱡ'#"
msgid "Toggle Cheatsheet"
msgstr "Tögglé Çhéätshéét Ⱡ'σ#"
#: cms/templates/widgets/problem-edit.html
msgid "Label"
msgstr "Läßél Ⱡ'σяєм ι#"
#: cms/templates/widgets/sock.html
msgid "Looking for Help with Studio?"
msgstr "Löökïng för Hélp wïth Stüdïö? Ⱡ'σяєм #"
......
......@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2014-02-11 18:19-0500\n"
"PO-Revision-Date: 2014-02-11 23:20:19.199916\n"
"POT-Creation-Date: 2014-02-14 16:00-0500\n"
"PO-Revision-Date: 2014-02-14 21:00:58.182145\n"
"Last-Translator: \n"
"Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n"
"MIME-Version: 1.0\n"
......@@ -101,6 +101,106 @@ msgstr "ünänswéréd Ⱡ#"
msgid "Status: unsubmitted"
msgstr "Stätüs: ünsüßmïttéd Ⱡ'σя#"
#. Translators: A "rating" is a score a student gives to indicate how well
#. they feel they were graded on this problem
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid "You need to pick a rating before you can submit."
msgstr "Ýöü nééd tö pïçk ä rätïng ßéföré ýöü çän süßmït. Ⱡ'σяєм ιρѕυм #"
#. Translators: this message appears when transitioning between openended
#. grading
#. types (i.e. self assesment to peer assessment). Sometimes, if a student
#. did not perform well at one step, they cannot move on to the next one.
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid "Your score did not meet the criteria to move to the next step."
msgstr ""
"Ýöür sçöré dïd nöt méét thé çrïtérïä tö mövé tö thé néxt stép. Ⱡ'σяєм ιρѕυм "
"∂σłσя#"
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
#: lms/static/coffee/src/staff_grading/staff_grading.js
msgid "Submit"
msgstr "Süßmït Ⱡ'σяєм ιρѕ#"
#. Translators: one clicks this button after one has finished filling out the
#. grading
#. form for an openended assessment
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid "Submit assessment"
msgstr "Süßmït ässéssmént Ⱡ'σ#"
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid ""
"Your response has been submitted. Please check back later for your grade."
msgstr ""
"Ýöür réspönsé häs ßéén süßmïttéd. Pléäsé çhéçk ßäçk lätér för ýöür grädé. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#"
#. Translators: this button is clicked to submit a student's rating of
#. an evaluator's assessment
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid "Submit post-assessment"
msgstr "Süßmït pöst-ässéssmént Ⱡ'σяє#"
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid "Answer saved, but not yet submitted."
msgstr "Ànswér sävéd, ßüt nöt ýét süßmïttéd. Ⱡ'σяєм ιρ#"
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid ""
"Please confirm that you wish to submit your work. You will not be able to "
"make any changes after submitting."
msgstr ""
"Pléäsé çönfïrm thät ýöü wïsh tö süßmït ýöür wörk. Ýöü wïll nöt ßé äßlé tö "
"mäké äný çhängés äftér süßmïttïng. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#"
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid ""
"You are trying to upload a file that is too large for our system. Please "
"choose a file under 2MB or paste a link to it into the answer box."
msgstr ""
"Ýöü äré trýïng tö üplöäd ä fïlé thät ïs töö lärgé för öür sýstém. Pléäsé "
"çhöösé ä fïlé ündér 2MB ör pästé ä lïnk tö ït ïntö thé änswér ßöx. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ι#"
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid ""
"Are you sure you want to remove your previous response to this question?"
msgstr ""
"Àré ýöü süré ýöü wänt tö rémövé ýöür prévïöüs réspönsé tö thïs qüéstïön? "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid "Moved to next step."
msgstr "Mövéd tö néxt stép. Ⱡ'σя#"
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid ""
"File uploads are required for this question, but are not supported in your "
"browser. Try the newest version of Google Chrome. Alternatively, if you have"
" uploaded the image to another website, you can paste a link to it into the "
"answer box."
msgstr ""
"Fïlé üplöäds äré réqüïréd för thïs qüéstïön, ßüt äré nöt süppörtéd ïn ýöür "
"ßröwsér. Trý thé néwést vérsïön öf Gööglé Çhrömé. Àltérnätïvélý, ïf ýöü hävé"
" üplöädéd thé ïmägé tö änöthér wéßsïté, ýöü çän pästé ä lïnk tö ït ïntö thé "
"änswér ßöx. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ "
"∂σ єιυѕмσ∂ тє#"
#. Translators: "Show Question" is some text that, when clicked, shows a
#. question's
#. content that had been hidden
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid "Show Question"
msgstr "Shöw Qüéstïön Ⱡ'#"
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
msgid "Hide Question"
msgstr "Hïdé Qüéstïön Ⱡ'#"
#: common/lib/xmodule/xmodule/js/src/sequence/display.js
msgid ""
"Sequence error! Cannot navigate to tab %(tab_name)s in the current "
......@@ -1009,11 +1109,11 @@ msgid "Try loading again"
msgstr "Trý löädïng ägäïn Ⱡ'σ#"
#: lms/static/coffee/src/staff_grading/staff_grading.js
msgid "<%= num %> available"
msgid "<%= num %> available "
msgstr "<%= num %> äväïläßlé Ⱡ'#"
#: lms/static/coffee/src/staff_grading/staff_grading.js
msgid "<%= num %> graded"
msgid "<%= num %> graded "
msgstr "<%= num %> grädéd Ⱡ#"
#: lms/static/coffee/src/staff_grading/staff_grading.js
......@@ -1021,10 +1121,6 @@ msgid "<%= num %> more needed to start ML"
msgstr "<%= num %> möré néédéd tö stärt ML Ⱡ'σяєм#"
#: lms/static/coffee/src/staff_grading/staff_grading.js
msgid "Submit"
msgstr "Süßmït Ⱡ'σяєм ιρѕ#"
#: lms/static/coffee/src/staff_grading/staff_grading.js
msgid "Re-check for submissions"
msgstr "Ré-çhéçk för süßmïssïöns Ⱡ'σяє#"
......
......@@ -530,3 +530,24 @@ defined::
Here we define ``_()`` as a pass-through function, so the string will be found
during extraction, but won't be translated too early. Then we use the real
translation function at runtime to get the localized string.
Multiline Strings
=================
Translator notes must directly prepend the string literals to which they refer.
For example, the translator note here will not be passed along to translators::
# Translators: you will not be able to see this note because
# I do not directly prepend the line with the translated string literal.
# See the line directly below this one does not contain part of the string?
long_translated_string = _(
"I am a long string, with many, many words. So many words that it is "
"advisable that I be split over this line."
)
In such a case, make sure you format your code so that the string begins on
a line directly below the translator note::
# Translators: you will be able to see this note.
# See how the line directly below this one contains the start of the string?
long_translated_string = _("I am a long string, with many, many words. "
"So many words that it is advisable that I "
"be split over this line.")
......@@ -15,7 +15,7 @@ Feature: LMS.Annotatable Component
And I click "Reply to annotation" on passage <problem>
Then I am scrolled to that annotation problem
When I answer that annotation problem
Then I recieve feedback on that annotation problem
Then I receive feedback on that annotation problem
When I click "Return to annotation" on that problem
Then I am scrolled to the annotatable component
......
......@@ -156,7 +156,7 @@ class AnnotatableSteps(object):
world.css_click(self.active_problem_selector('.check'))
def check_feedback(self, step):
r"""I recieve feedback on that annotation problem$"""
r"""I receive feedback on that annotation problem$"""
world.wait_for_visible(self.active_problem_selector('.tag-status.correct'))
assert_equals(len(world.css_find(self.active_problem_selector('.tag-status.correct'))), 1)
assert_equals(len(world.css_find(self.active_problem_selector('.show'))), 1)
......
......@@ -25,7 +25,15 @@
% endif
><i class="icon-chevron-left"></i></button>
% endif
${result['task_name']} from grader ${i+1}
## Translators: an example of what this string will look
## like is: "Scored rubric from grader 1", where
## "Scored rubric" replaces {result_of_task} and
## "1" replaces {number}.
## This string appears when a user is viewing one of
## their graded rubrics for an openended response problem.
## the number distinguishes between the different
## graded rubrics the user might have received
${_("{result_of_task} from grader {number}").format(result_of_task = result['task_name'], number = i + 1)}
% if num_results>1:
<button href="#" alt="Next" class="rubric-button rubric-next-button"
% if (i+1) >= num_results:
......@@ -45,4 +53,3 @@
%endif
% endfor
......@@ -19,7 +19,11 @@
%if len(co['feedback'])>2:
<div class="collapsible evaluation-response">
<header>
<a href="#">${_("See full feedback")}</a>
## Translators: "See full feedback" is the text of
## a link that allows a user to see more detailed
## feedback from a self, peer, or instructor
## graded openended problem
<a href="#" class="see-full-feedback">${_("See full feedback")}</a>
</header>
<section class="feedback-full">
${co['feedback']}
......@@ -33,7 +37,10 @@
<input type="hidden" value="${co['submission_id']}" class="submission_id" />
<div class="collapsible evaluation-response">
<header>
<a href="#">${_("Respond to Feedback")}</a>
## Translators: this text forms a link that, when
## clicked, allows a user to respond to the feedback
## the user received on his or her openended problem
<a href="#" class="respond-to-feedback">${_("Respond to Feedback")}</a>
</header>
<section id="evaluation" class="evaluation">
<p>${_("How accurate do you find this feedback?")}</p>
......
......@@ -7,7 +7,10 @@
<div class="visibility-control visibility-control-response">
<div class="inner">
</div>
<label class="section-header section-header-response" for="answer_${module_id}">Response</label>
<label class="section-header section-header-response" for="answer_${module_id}">
## Translators: "Response" labels an area that contains the user's
## Response to an openended problem. It is a noun.
${_("Response")}</label>
</div>
<textarea rows="${rows}" cols="${cols}" name="answer" class="answer short-form-response" id="answer_${module_id}">${previous_answer|h}</textarea>
......
......@@ -3,7 +3,10 @@
${msg|n}
<div class="collapsible evaluation-response">
<header>
<a href="#">${_("Respond to Feedback")}</a>
## Translators: when "Respond to Feedback" is clicked, a survey
## appears on which a user can respond to the feedback the user
## received on an openended problem
<a href="#" class="respond-to-feedback">${_("Respond to Feedback")}</a>
</header>
<section id="evaluation_${id}" class="evaluation">
<p>${_("How accurate do you find this feedback?")}</p>
......
......@@ -8,7 +8,10 @@
<div class="visibility-control visibility-control-response">
<div class="inner">
</div>
<label class="section-header section-header-response" for="answer_${module_id}">Response</label>
<label class="section-header section-header-response" for="answer_${module_id}">
## Translators: "Response" labels a text area into which a user enters
## his or her response to a prompt from an openended problem.
${_("Response")}</label>
</div>
<div>
<textarea name="answer" class="answer short-form-response" cols="70" rows="20" id="answer_${module_id}">${previous_answer|n}</textarea>
......
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