Merge pull request #9630 from edx/rc/2015-09-09

Release 2015-09-09
This commit is contained in:
Clinton Blackburn
2015-09-09 11:04:27 -04:00
271 changed files with 13763 additions and 3674 deletions

View File

@@ -233,4 +233,6 @@ Dongwook Yoon <dy252@cornell.edu>
Awais Qureshi <awais.qureshi@arbisoft.com>
Eric Fischer <efischer@edx.org>
Brian Beggs <macdiesel@gmail.com>
Bill DeRusha <bill@edx.org>
Bill DeRusha <bill@edx.org>
Kevin Falcone <kevin@edx.org>
Mirjam Škarica <mirjamskarica@gmail.com>

View File

@@ -67,20 +67,20 @@ def _click_advanced():
world.wait_for_visible(tab2_css)
def _find_matching_link(category, component_type):
def _find_matching_button(category, component_type):
"""
Find the link with the specified text. There should be one and only one.
Find the button with the specified text. There should be one and only one.
"""
# The tab shows links for the given category
links = world.css_find('div.new-component-{} a'.format(category))
# The tab shows buttons for the given category
buttons = world.css_find('div.new-component-{} button'.format(category))
# Find the link whose text matches what you're looking for
matched_links = [link for link in links if link.text == component_type]
# Find the button whose text matches what you're looking for
matched_buttons = [btn for btn in buttons if btn.text == component_type]
# There should be one and only one
assert_equal(len(matched_links), 1)
return matched_links[0]
assert_equal(len(matched_buttons), 1)
return matched_buttons[0]
def click_component_from_menu(category, component_type, is_advanced):
@@ -100,7 +100,7 @@ def click_component_from_menu(category, component_type, is_advanced):
# Retry this in case the list is empty because you tried too fast.
link = world.retry_on_exception(
lambda: _find_matching_link(category, component_type),
lambda: _find_matching_button(category, component_type),
ignored_exceptions=AssertionError
)

View File

@@ -18,18 +18,6 @@ from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
def print_out_all_courses():
"""
Print out all the courses available in the course_key format so that
the user can correct any course_key mistakes
"""
courses = modulestore().get_courses_keys()
print 'Available courses:'
for course in courses:
print str(course)
print ''
class Command(BaseCommand):
"""
Delete a MongoDB backed course
@@ -58,8 +46,6 @@ class Command(BaseCommand):
elif len(args) > 2:
raise CommandError("Too many arguments! Expected <course_key> <commit>")
print_out_all_courses()
if not modulestore().get_course(course_key):
raise CommandError("Course with '%s' key not found." % args[0])
@@ -67,4 +53,4 @@ class Command(BaseCommand):
if query_yes_no("Deleting course {0}. Confirm?".format(course_key), default="no"):
if query_yes_no("Are you sure. This action cannot be undone!", default="no"):
delete_course_and_groups(course_key, ModuleStoreEnum.UserID.mgmt_command)
print_out_all_courses()
print "Deleted course {}".format(course_key)

View File

@@ -0,0 +1,115 @@
""" Management command to update courses' search index """
import logging
from django.core.management import BaseCommand, CommandError
from optparse import make_option
from textwrap import dedent
from contentstore.courseware_index import CoursewareSearchIndexer
from search.search_engine_base import SearchEngine
from elasticsearch import exceptions
from opaque_keys.edx.keys import CourseKey
from opaque_keys import InvalidKeyError
from opaque_keys.edx.locator import CourseLocator
from .prompt import query_yes_no
from xmodule.modulestore.django import modulestore
class Command(BaseCommand):
"""
Command to re-index courses
Examples:
./manage.py reindex_course <course_id_1> <course_id_2> - reindexes courses with keys course_id_1 and course_id_2
./manage.py reindex_course --all - reindexes all available courses
./manage.py reindex_course --setup - reindexes all courses for devstack setup
"""
help = dedent(__doc__)
can_import_settings = True
args = "<course_id course_id ...>"
all_option = make_option('--all',
action='store_true',
dest='all',
default=False,
help='Reindex all courses')
setup_option = make_option('--setup',
action='store_true',
dest='setup',
default=False,
help='Reindex all courses on developers stack setup')
option_list = BaseCommand.option_list + (all_option, setup_option)
CONFIRMATION_PROMPT = u"Re-indexing all courses might be a time consuming operation. Do you want to continue?"
def _parse_course_key(self, raw_value):
""" Parses course key from string """
try:
result = CourseKey.from_string(raw_value)
except InvalidKeyError:
raise CommandError("Invalid course_key: '%s'." % raw_value)
if not isinstance(result, CourseLocator):
raise CommandError(u"Argument {0} is not a course key".format(raw_value))
return result
def handle(self, *args, **options):
"""
By convention set by Django developers, this method actually executes command's actions.
So, there could be no better docstring than emphasize this once again.
"""
all_option = options.get('all', False)
setup_option = options.get('setup', False)
index_all_courses_option = all_option or setup_option
if len(args) == 0 and not index_all_courses_option:
raise CommandError(u"reindex_course requires one or more arguments: <course_id>")
store = modulestore()
if index_all_courses_option:
index_name = CoursewareSearchIndexer.INDEX_NAME
doc_type = CoursewareSearchIndexer.DOCUMENT_TYPE
if setup_option:
try:
# try getting the ElasticSearch engine
searcher = SearchEngine.get_search_engine(index_name)
except exceptions.ElasticsearchException as exc:
logging.exception('Search Engine error - %s', unicode(exc))
return
index_exists = searcher._es.indices.exists(index=index_name) # pylint: disable=protected-access
doc_type_exists = searcher._es.indices.exists_type( # pylint: disable=protected-access
index=index_name,
doc_type=doc_type
)
index_mapping = searcher._es.indices.get_mapping( # pylint: disable=protected-access
index=index_name,
doc_type=doc_type
) if index_exists and doc_type_exists else {}
if index_exists and index_mapping:
return
# if reindexing is done during devstack setup step, don't prompt the user
if setup_option or query_yes_no(self.CONFIRMATION_PROMPT, default="no"):
# in case of --setup or --all, get the list of course keys from all courses
# that are stored in the modulestore
course_keys = [course.id for course in modulestore().get_courses()]
else:
return
else:
# in case course keys are provided as arguments
course_keys = map(self._parse_course_key, args)
for course_key in course_keys:
CoursewareSearchIndexer.do_course_reindex(store, course_key)

View File

@@ -5,6 +5,7 @@ Unittests for deleting a course in an chosen modulestore
import unittest
import mock
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from django.core.management import CommandError
from contentstore.management.commands.delete_course import Command # pylint: disable=import-error
from contentstore.tests.utils import CourseTestCase # pylint: disable=import-error
@@ -94,27 +95,23 @@ class DeleteCourseTest(CourseTestCase):
run=course_run
)
def test_courses_keys_listing(self):
"""
Test if the command lists out available course key courses
"""
courses = [str(key) for key in modulestore().get_courses_keys()]
self.assertIn("TestX/TS01/2015_Q1", courses)
def test_course_key_not_found(self):
"""
Test for when a non-existing course key is entered
"""
errstring = "Course with 'TestX/TS01/2015_Q7' key not found."
with self.assertRaisesRegexp(CommandError, errstring):
self.command.handle("TestX/TS01/2015_Q7", "commit")
self.command.handle('TestX/TS01/2015_Q7', "commit")
def test_course_deleted(self):
"""
Testing if the entered course was deleted
"""
#Test if the course that is about to be deleted exists
self.assertIsNotNone(modulestore().get_course(SlashSeparatedCourseKey("TestX", "TS01", "2015_Q1")))
with mock.patch(self.YESNO_PATCH_LOCATION) as patched_yes_no:
patched_yes_no.return_value = True
self.command.handle("TestX/TS01/2015_Q1", "commit")
courses = [unicode(key) for key in modulestore().get_courses_keys()]
self.assertNotIn("TestX/TS01/2015_Q1", courses)
self.command.handle('TestX/TS01/2015_Q1', "commit")
self.assertIsNone(modulestore().get_course(SlashSeparatedCourseKey("TestX", "TS01", "2015_Q1")))

View File

@@ -0,0 +1,131 @@
""" Tests for course reindex command """
import ddt
from django.core.management import call_command, CommandError
import mock
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from common.test.utils import nostderr
from xmodule.modulestore.tests.factories import CourseFactory, LibraryFactory
from contentstore.management.commands.reindex_course import Command as ReindexCommand
from contentstore.courseware_index import SearchIndexingError
@ddt.ddt
class TestReindexCourse(ModuleStoreTestCase):
""" Tests for course reindex command """
def setUp(self):
""" Setup method - create courses """
super(TestReindexCourse, self).setUp()
self.store = modulestore()
self.first_lib = LibraryFactory.create(
org="test", library="lib1", display_name="run1", default_store=ModuleStoreEnum.Type.split
)
self.second_lib = LibraryFactory.create(
org="test", library="lib2", display_name="run2", default_store=ModuleStoreEnum.Type.split
)
self.first_course = CourseFactory.create(
org="test", course="course1", display_name="run1"
)
self.second_course = CourseFactory.create(
org="test", course="course2", display_name="run1"
)
REINDEX_PATH_LOCATION = 'contentstore.management.commands.reindex_course.CoursewareSearchIndexer.do_course_reindex'
MODULESTORE_PATCH_LOCATION = 'contentstore.management.commands.reindex_course.modulestore'
YESNO_PATCH_LOCATION = 'contentstore.management.commands.reindex_course.query_yes_no'
def _get_lib_key(self, library):
""" Get's library key as it is passed to indexer """
return library.location.library_key
def _build_calls(self, *courses):
""" Builds a list of mock.call instances representing calls to reindexing method """
return [mock.call(self.store, course.id) for course in courses]
def test_given_no_arguments_raises_command_error(self):
""" Test that raises CommandError for incorrect arguments """
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(CommandError, ".* requires one or more arguments .*"):
call_command('reindex_course')
@ddt.data('qwerty', 'invalid_key', 'xblock-v1:qwe+rty')
def test_given_invalid_course_key_raises_not_found(self, invalid_key):
""" Test that raises InvalidKeyError for invalid keys """
errstring = "Invalid course_key: '%s'." % invalid_key
with self.assertRaises(SystemExit) as ex:
with self.assertRaisesRegexp(CommandError, errstring):
call_command('reindex_course', invalid_key)
self.assertEqual(ex.exception.code, 1)
def test_given_library_key_raises_command_error(self):
""" Test that raises CommandError if library key is passed """
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(SearchIndexingError, ".* is not a course key"):
call_command('reindex_course', unicode(self._get_lib_key(self.first_lib)))
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(SearchIndexingError, ".* is not a course key"):
call_command('reindex_course', unicode(self._get_lib_key(self.second_lib)))
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(SearchIndexingError, ".* is not a course key"):
call_command(
'reindex_course',
unicode(self.second_course.id),
unicode(self._get_lib_key(self.first_lib))
)
def test_given_id_list_indexes_courses(self):
""" Test that reindexes courses when given single course key or a list of course keys """
with mock.patch(self.REINDEX_PATH_LOCATION) as patched_index, \
mock.patch(self.MODULESTORE_PATCH_LOCATION, mock.Mock(return_value=self.store)):
call_command('reindex_course', unicode(self.first_course.id))
self.assertEqual(patched_index.mock_calls, self._build_calls(self.first_course))
patched_index.reset_mock()
call_command('reindex_course', unicode(self.second_course.id))
self.assertEqual(patched_index.mock_calls, self._build_calls(self.second_course))
patched_index.reset_mock()
call_command(
'reindex_course',
unicode(self.first_course.id),
unicode(self.second_course.id)
)
expected_calls = self._build_calls(self.first_course, self.second_course)
self.assertEqual(patched_index.mock_calls, expected_calls)
def test_given_all_key_prompts_and_reindexes_all_courses(self):
""" Test that reindexes all courses when --all key is given and confirmed """
with mock.patch(self.YESNO_PATCH_LOCATION) as patched_yes_no:
patched_yes_no.return_value = True
with mock.patch(self.REINDEX_PATH_LOCATION) as patched_index, \
mock.patch(self.MODULESTORE_PATCH_LOCATION, mock.Mock(return_value=self.store)):
call_command('reindex_course', all=True)
patched_yes_no.assert_called_once_with(ReindexCommand.CONFIRMATION_PROMPT, default='no')
expected_calls = self._build_calls(self.first_course, self.second_course)
self.assertItemsEqual(patched_index.mock_calls, expected_calls)
def test_given_all_key_prompts_and_reindexes_all_courses_cancelled(self):
""" Test that does not reindex anything when --all key is given and cancelled """
with mock.patch(self.YESNO_PATCH_LOCATION) as patched_yes_no:
patched_yes_no.return_value = False
with mock.patch(self.REINDEX_PATH_LOCATION) as patched_index, \
mock.patch(self.MODULESTORE_PATCH_LOCATION, mock.Mock(return_value=self.store)):
call_command('reindex_course', all=True)
patched_yes_no.assert_called_once_with(ReindexCommand.CONFIRMATION_PROMPT, default='no')
patched_index.assert_not_called()
def test_fail_fast_if_reindex_fails(self):
""" Test that fails on first reindexing exception """
with mock.patch(self.REINDEX_PATH_LOCATION) as patched_index:
patched_index.side_effect = SearchIndexingError("message", [])
with self.assertRaises(SearchIndexingError):
call_command('reindex_course', unicode(self.second_course.id))

View File

@@ -170,6 +170,9 @@ FEATURES = {
# Teams feature
'ENABLE_TEAMS': True,
# Teams search feature
'ENABLE_TEAMS_SEARCH': False,
# Show video bumper in Studio
'ENABLE_VIDEO_BUMPER': False,

View File

@@ -281,5 +281,8 @@ SEARCH_ENGINE = "search.tests.mock_search_engine.MockSearchEngine"
# teams feature
FEATURES['ENABLE_TEAMS'] = True
# teams search
FEATURES['ENABLE_TEAMS_SEARCH'] = True
# Dummy secret key for dev/test
SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd'

View File

@@ -79,7 +79,7 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails
};
beforeEach(function() {
TemplateHelpers.installTemplates(['certificate-details', 'signatory-details', 'signatory-editor'], true);
TemplateHelpers.installTemplates(['certificate-details', 'signatory-details', 'signatory-editor', 'signatory-actions'], true);
this.newModelOptions = {add: true};
this.model = new CertificateModel({

View File

@@ -40,6 +40,7 @@ function ($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, Sign
eventAgg: this.eventAgg
});
this.template = this.loadTemplate('signatory-details');
this.signatory_action_template = this.loadTemplate('signatory-actions');
},
loadTemplate: function(name) {
@@ -51,6 +52,7 @@ function ($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, Sign
// Retrieve the edit view for this model
if (event && event.preventDefault) { event.preventDefault(); }
this.$el.html(this.edit_view.render());
$(this.signatory_action_template()).appendTo(this.el);
this.edit_view.delegateEvents();
this.delegateEvents();
},

View File

@@ -552,7 +552,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
var clickNewComponent;
clickNewComponent = function (index) {
containerPage.$(".new-component .new-component-type a.single-template")[index].click();
containerPage.$(".new-component .new-component-type button.single-template")[index].click();
};
it('Attaches a handler to new component button', function() {
@@ -598,7 +598,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
var showTemplatePicker, verifyCreateHtmlComponent;
showTemplatePicker = function () {
containerPage.$('.new-component .new-component-type a.multiple-templates')[0].click();
containerPage.$('.new-component .new-component-type button.multiple-templates')[0].click();
};
verifyCreateHtmlComponent = function (test, templateIndex, expectedRequest) {
@@ -606,7 +606,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
renderContainerPage(test, mockContainerXBlockHtml);
showTemplatePicker();
xblockCount = containerPage.$('.studio-xblock-wrapper').length;
containerPage.$('.new-component-html a')[templateIndex].click();
containerPage.$('.new-component-html button')[templateIndex].click();
EditHelpers.verifyXBlockRequest(requests, expectedRequest);
AjaxHelpers.respondWithJson(requests, {"locator": "new_item"});
respondWithHtml(mockXBlockHtml);

View File

@@ -89,24 +89,24 @@ function ($, AjaxHelpers, ViewHelpers, ManageUsersFactory, ViewUtils) {
it("displays an error when the user has already been added", function () {
var requests = AjaxHelpers.requests(this);
var promptSpy = ViewHelpers.createPromptSpy();
$('.create-user-button').click();
$('.user-email-input').val('honor@example.com');
var warningPromptSelector = '.wrapper-prompt.is-shown .prompt.warning';
expect($(warningPromptSelector).length).toEqual(0);
$('.form-create.create-user .action-primary').click();
expect($(warningPromptSelector).length).toEqual(1);
expect($(warningPromptSelector)).toContainText('Already a library team member');
ViewHelpers.verifyPromptShowing(promptSpy, 'Already a library team member');
expect(requests.length).toEqual(0);
});
it("can remove a user's permission to access the library", function () {
var requests = AjaxHelpers.requests(this);
var promptSpy = ViewHelpers.createPromptSpy();
var reloadSpy = spyOn(ViewUtils, 'reload');
var email = "honor@example.com";
$('.user-item[data-email="'+email+'"] .action-delete .delete').click();
expect($('.wrapper-prompt.is-shown .prompt.warning').length).toEqual(1);
$('.wrapper-prompt.is-shown .action-primary').click();
ViewHelpers.verifyPromptShowing(promptSpy, 'Are you sure?');
ViewHelpers.confirmPrompt(promptSpy);
ViewHelpers.verifyPromptHidden(promptSpy);
AjaxHelpers.expectJsonRequest(requests, 'DELETE', getUrl(email), {role: null});
AjaxHelpers.respondWithJson(requests, {'result': 'ok'});
expect(reloadSpy).toHaveBeenCalled();

View File

@@ -6,10 +6,10 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "common/js/compo
function ($, _, gettext, BaseView, ViewUtils, AddXBlockButton, AddXBlockMenu) {
var AddXBlockComponent = BaseView.extend({
events: {
'click .new-component .new-component-type a.multiple-templates': 'showComponentTemplates',
'click .new-component .new-component-type a.single-template': 'createNewComponent',
'click .new-component .new-component-type button.multiple-templates': 'showComponentTemplates',
'click .new-component .new-component-type button.single-template': 'createNewComponent',
'click .new-component .cancel-button': 'closeNewComponent',
'click .new-component-templates .new-component-template a': 'createNewComponent',
'click .new-component-templates .new-component-template .button-component': 'createNewComponent',
'click .new-component-templates .cancel-button': 'closeNewComponent'
},
@@ -43,13 +43,17 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "common/js/compo
type = $(event.currentTarget).data('type');
this.$('.new-component').slideUp(250);
this.$('.new-component-' + type).slideDown(250);
this.$('.new-component-' + type + ' div').focus();
},
closeNewComponent: function(event) {
event.preventDefault();
event.stopPropagation();
type = $(event.currentTarget).data('type');
this.$('.new-component').slideDown(250);
this.$('.new-component-templates').slideUp(250);
this.$('ul.new-component-type li button[data-type=' + type + ']').focus();
},
createNewComponent: function(event) {

View File

@@ -13,40 +13,35 @@
.large-advanced-icon {
display: inline-block;
width: 100px;
height: 60px;
margin-right: ($baseline/4);
width: ($baseline*3);
height: ($baseline*3);
background: url(../images/large-advanced-icon.png) center no-repeat;
}
.large-discussion-icon {
display: inline-block;
width: 100px;
height: 60px;
margin-right: ($baseline/4);
width: ($baseline*3);
height: ($baseline*3);
background: url(../images/large-discussion-icon.png) center no-repeat;
}
.large-html-icon {
display: inline-block;
width: 100px;
height: 60px;
margin-right: ($baseline/4);
width: ($baseline*3);
height: ($baseline*3);
background: url(../images/large-html-icon.png) center no-repeat;
}
.large-problem-icon {
display: inline-block;
width: 100px;
height: 60px;
margin-right: ($baseline/4);
width: ($baseline*3);
height: ($baseline*3);
background: url(../images/large-problem-icon.png) center no-repeat;
}
.large-video-icon {
display: inline-block;
width: 100px;
height: 60px;
margin-right: ($baseline/4);
width: ($baseline*3);
height: ($baseline*3);
background: url(../images/large-video-icon.png) center no-repeat;
}

View File

@@ -130,9 +130,10 @@
width: ($baseline*5);
height: ($baseline*5);
margin-bottom: ($baseline/2);
box-shadow: 0 1px 1px $shadow, 0 1px 0 rgba(255, 255, 255, .4) inset;
border: 1px solid $green-d2;
border-radius: ($baseline/4);
box-shadow: 0 1px 1px $shadow, 0 1px 0 rgba(255, 255, 255, .4) inset;
padding: 0;
background-color: $green-l1;
text-align: center;
color: $white;
@@ -195,16 +196,17 @@
}
}
a {
.button-component {
@include clearfix();
@include transition(none);
@extend %t-demi-strong;
display: block;
width: 100%;
border: 0px;
padding: 7px $baseline;
background: $white;
color: $gray-d3;
text-align: left;
&:hover {
@include transition(background-color $tmg-f2 linear 0s);

View File

@@ -380,6 +380,12 @@
color: $gray-l3;
}
}
&.custom-signatory-action {
position: relative;
top: 0;
left: 0;
opacity: 1.0;
}
}
.copy {
@@ -522,6 +528,10 @@
.signatory-panel-body {
padding: $baseline;
.signatory-image {
margin-top: 20px;
}
}
.signatory-panel-body label {

View File

@@ -11,7 +11,7 @@ from django.utils.translation import ugettext as _
<%block name="bodyclass">is-signedin course view-certificates</%block>
<%block name="header_extras">
% for template_name in ["certificate-details", "certificate-editor", "signatory-editor", "signatory-details", "basic-modal", "modal-button", "list", "upload-dialog", "certificate-web-preview"]:
% for template_name in ["certificate-details", "certificate-editor", "signatory-editor", "signatory-details", "basic-modal", "modal-button", "list", "upload-dialog", "certificate-web-preview", "signatory-actions"]:
<script type="text/template" id="${template_name}-tpl">
<%static:include path="js/${template_name}.underscore" />
</script>

View File

@@ -1,8 +1,9 @@
<% if (type === 'advanced' || templates.length > 1) { %>
<a href="#" class="multiple-templates add-xblock-component-button" data-type="<%= type %>">
<button type="button" class="multiple-templates add-xblock-component-button" data-type="<%= type %>">
<% } else { %>
<a href="#" class="single-template add-xblock-component-button" data-type="<%= type %>" data-category="<%= templates[0].category %>">
<button type="button" class="single-template add-xblock-component-button" data-type="<%= type %>" data-category="<%= templates[0].category %>">
<% } %>
<span class="large-template-icon large-<%= type %>-icon"></span>
<span class="sr"> <%= gettext("Add Component:") %></span>
<span class="name"><%= display_name %></span>
</a>
</button>

View File

@@ -1,5 +1,11 @@
<div class="tab-group tabs">
<ul class="problem-type-tabs nav-tabs">
<div class="tab-group tabs" tabindex="-1" role="dialog" aria-label="<%-
interpolate(
gettext('%(type)s Component Template Menu'),
{type: type},
true
)
%>">
<ul class="problem-type-tabs nav-tabs" tabindex='-1'>
<li class="current">
<a class="link-tab" href="#tab1"><%= gettext("Common Problem Types") %></a>
</li>
@@ -13,16 +19,16 @@
<% if (templates[i].tab == "common") { %>
<% if (!templates[i].boilerplate_name) { %>
<li class="editor-md empty">
<a href="#" data-category="<%= templates[i].category %>">
<button type="button" class="button-component" data-category="<%= templates[i].category %>">
<span class="name"><%= templates[i].display_name %></span>
</a>
</button>
</li>
<% } else { %>
<li class="editor-md">
<a href="#" data-category="<%= templates[i].category %>"
<button type="button" class="button-component" data-category="<%= templates[i].category %>"
data-boilerplate="<%= templates[i].boilerplate_name %>">
<span class="name"><%= templates[i].display_name %></span>
</a>
</button>
</li>
<% } %>
<% } %>
@@ -34,14 +40,14 @@
<% for (var i = 0; i < templates.length; i++) { %>
<% if (templates[i].tab == "advanced") { %>
<li class="editor-manual">
<a href="#" data-category="<%= templates[i].category %>"
<button type="button" class="button-component" data-category="<%= templates[i].category %>"
data-boilerplate="<%= templates[i].boilerplate_name %>">
<span class="name"><%= templates[i].display_name %></span>
</a>
</button>
</li>
<% } %>
<% } %>
</ul>
</div>
<button class="cancel-button" data-type="<%= type %>"><%= gettext("Cancel") %></button>
</div>
<a href="#" class="cancel-button"><%= gettext("Cancel") %></a>

View File

@@ -1,23 +1,29 @@
<% if (type === 'advanced' || templates.length > 1) { %>
<div class="tab current" id="tab1">
<div class="tab current" id="tab1" tabindex="-1" role="dialog" aria-label="<%-
interpolate(
gettext('%(type)s Component Template Menu'),
{type: type},
true
)
%>">
<ul class="new-component-template">
<% for (var i = 0; i < templates.length; i++) { %>
<% if (!templates[i].boilerplate_name) { %>
<li class="editor-md empty">
<a href="#" data-category="<%= templates[i].category %>">
<button type="button" class="button-component" data-category="<%= templates[i].category %>">
<span class="name"><%= templates[i].display_name %></span>
</a>
</button>
</li>
<% } else { %>
<li class="editor-md">
<a href="#" data-category="<%= templates[i].category %>"
<button type="button" class="button-component" data-category="<%= templates[i].category %>"
data-boilerplate="<%= templates[i].boilerplate_name %>">
<span class="name"><%= templates[i].display_name %></span>
</a>
</button>
</li>
<% } %>
<% } %>
</ul>
<button class="cancel-button" data-type="<%= type %>"><%= gettext("Cancel") %></button>
</div>
<a href="#" class="cancel-button"><%= gettext("Cancel") %></a>
<% } %>

View File

@@ -17,12 +17,12 @@
<span class="title"><%= gettext("Certificate Details") %></span>
</header>
<div class="actual-course-title">
<span class="certificate-label"><%= gettext('Course Title') %>: </span>
<span class="certificate-label"><b><%= gettext('Course Title') %>: </b> </span>
<span class="certificate-value"><%= course.get('name') %></span>
</div>
<% if (course_title) { %>
<div class="course-title-override">
<span class="certificate-label"><%= gettext('Course Title Override') %>: </span>
<span class="certificate-label"><b><%= gettext('Course Title Override') %>: </b></span>
<span class="certificate-value"><%= course_title %></span>
</div>
<% } %>

View File

@@ -19,6 +19,10 @@
<textarea id="certificate-description-<%= uniqueId %>" class="certificate-description-input text input-text" name="certificate-description" placeholder="<%= gettext("Description of the certificate") %>" aria-describedby="certificate-description-<%=uniqueId %>-tip"><%= description %></textarea>
<span id="certificate-description-<%= uniqueId %>-tip" class="tip tip-stacked"><%= gettext("Description of the certificate") %></span>
</div>
<div class="field text actual-course-title">
<label class="actual-course-title"><b><%= gettext("Course Title") %></b></label>
<span class="actual-title"><%= course.get('name') %></span>
</div>
<div class="input-wrap field text add-certificate-course-title">
<label for="certificate-course-title-<%= uniqueId %>"><%= gettext("Course Title Override") %></label>
<input id="certificate-course-title-<%= uniqueId %>" class="certificate-course-title-input input-text" name="certificate-course-title" type="text" placeholder="<%= gettext("Course title") %>" value="<%= course_title %>" aria-describedby="certificate-course-title-<%=uniqueId %>-tip" />

View File

@@ -0,0 +1,6 @@
<div class="collection-edit">
<div class="actions custom-signatory-action">
<button class="signatory-panel-save action action-primary" type="submit"><%= gettext("Save") %></button>
<button class="signatory-panel-close action action-secondary action-cancel"><%= gettext("Cancel") %></button>
</div>
</div>

View File

@@ -9,16 +9,25 @@
<div class="signatory-panel-header">Signatory <%= signatory_number %>&nbsp;</div>
<div class="signatory-panel-body">
<div>
<span class="signatory-name-label"><%= gettext("Name") %>:&nbsp;</span>
<span class="signatory-name-value"><%= name %></span>
<div>
<span class="signatory-name-label"><b><%= gettext("Name") %>:</b>&nbsp;</span>
<span class="signatory-name-value"><%= name %></span>
</div>
<div>
<span class="signatory-title-label"><b><%= gettext("Title") %>:</b>&nbsp;</span>
<span class="signatory-title-value"><%= title %></span>
</div>
<div>
<span class="signatory-organization-label"><b><%= gettext("Organization") %>:</b>&nbsp;</span>
<span class="signatory-organization-value"><%= organization %></span>
</div>
</div>
<div>
<span class="signatory-title-label"><%= gettext("Title") %>:&nbsp;</span>
<span class="signatory-title-value"><%= title %></span>
</div>
<div>
<span class="signatory-organization-label"><%= gettext("Organization") %>:&nbsp;</span>
<span class="signatory-organization-value"><%= organization %></span>
<div class="signatory-image">
<% if (signature_image_path != "") { %>
<div class="wrapper-signature-image">
<img class="signature-image" src="<%= signature_image_path %>" alt="Signature Image">
</div>
<% } %>
</div>
</div>
</div>

View File

@@ -1,15 +1,5 @@
<div class="signatory-panel-default">
<% if (!is_editing_all_collections) { %>
<a class="signatory-panel-close" href="javascript:void(0);" data-tooltip="Close">
<i class="icon fa fa-close" aria-hidden="true"></i>
<span class="sr action-button-text"><%= gettext("Close") %></span>
</a>
<a class="signatory-panel-save" href="javascript:void(0);" data-tooltip="Save">
<i class="icon fa fa-save" aria-hidden="true"></i>
<span class="sr action-button-text"><%= gettext("Save") %></span>
</a>
<% } else if (signatories_count > 1 && (total_saved_signatories > 1 || isNew) ) { %>
<% if (is_editing_all_collections && signatories_count > 1 && (total_saved_signatories > 1 || isNew) ) { %>
<a class="signatory-panel-delete" href="#" data-tooltip="Delete">
<i class="icon fa fa-trash-o" aria-hidden="true"></i>
<span class="sr action-button-text"><%= gettext("Delete") %></span>

View File

@@ -189,7 +189,7 @@ def auth_pipeline_urls(auth_entry, redirect_url=None):
return {
provider.provider_id: third_party_auth.pipeline.get_login_url(
provider.provider_id, auth_entry, redirect_url=redirect_url
) for provider in third_party_auth.provider.Registry.enabled()
) for provider in third_party_auth.provider.Registry.accepting_logins()
}

View File

@@ -1046,9 +1046,10 @@ class CourseEnrollment(models.Model):
`course_key` is our usual course_id string (e.g. "edX/Test101/2013_Fall)
`mode` is a string specifying what kind of enrollment this is. The
default is "honor", meaning honor certificate. Future options
may include "audit", "verified_id", etc. Please don't use it
until we have these mapped out.
default is 'honor', meaning honor certificate. Other options
include 'professional', 'verified', 'audit',
'no-id-professional' and 'credit'.
See CourseMode in common/djangoapps/course_modes/models.py.
`check_access`: if True, we check that an accessible course actually
exists for the given course_key before we enroll the student.

View File

@@ -447,10 +447,11 @@ def register_user(request, extra_context=None):
if third_party_auth.is_enabled() and pipeline.running(request):
running_pipeline = pipeline.get(request)
current_provider = provider.Registry.get_from_pipeline(running_pipeline)
overrides = current_provider.get_register_form_data(running_pipeline.get('kwargs'))
overrides['running_pipeline'] = running_pipeline
overrides['selected_provider'] = current_provider.name
context.update(overrides)
if current_provider is not None:
overrides = current_provider.get_register_form_data(running_pipeline.get('kwargs'))
overrides['running_pipeline'] = running_pipeline
overrides['selected_provider'] = current_provider.name
context.update(overrides)
return render_to_response('register.html', context)
@@ -1769,6 +1770,10 @@ def auto_auth(request):
full_name = request.GET.get('full_name', username)
is_staff = request.GET.get('staff', None)
course_id = request.GET.get('course_id', None)
# mode has to be one of 'honor'/'professional'/'verified'/'audit'/'no-id-professional'/'credit'
enrollment_mode = request.GET.get('enrollment_mode', 'honor')
course_key = None
if course_id:
course_key = CourseLocator.from_string(course_id)
@@ -1816,7 +1821,7 @@ def auto_auth(request):
# Enroll the user in a course
if course_key is not None:
CourseEnrollment.enroll(user, course_key)
CourseEnrollment.enroll(user, course_key, mode=enrollment_mode)
# Apply the roles
for role_name in role_names:

View File

@@ -6,7 +6,7 @@ Admin site configuration for third party authentication
from django.contrib import admin
from config_models.admin import ConfigurationModelAdmin, KeyedConfigurationModelAdmin
from .models import OAuth2ProviderConfig, SAMLProviderConfig, SAMLConfiguration, SAMLProviderData
from .models import OAuth2ProviderConfig, SAMLProviderConfig, SAMLConfiguration, SAMLProviderData, LTIProviderConfig
from .tasks import fetch_saml_metadata
@@ -88,3 +88,26 @@ class SAMLProviderDataAdmin(admin.ModelAdmin):
return self.readonly_fields
admin.site.register(SAMLProviderData, SAMLProviderDataAdmin)
class LTIProviderConfigAdmin(KeyedConfigurationModelAdmin):
""" Django Admin class for LTIProviderConfig """
exclude = (
'icon_class',
'secondary',
)
def get_list_display(self, request):
""" Don't show every single field in the admin change list """
return (
'name',
'enabled',
'lti_consumer_key',
'lti_max_timestamp_age',
'change_date',
'changed_by',
'edit_link',
)
admin.site.register(LTIProviderConfig, LTIProviderConfigAdmin)

View File

@@ -0,0 +1,202 @@
"""
Third-party-auth module for Learning Tools Interoperability
"""
import logging
import calendar
import time
from django.contrib.auth import REDIRECT_FIELD_NAME
from oauthlib.common import Request
from oauthlib.oauth1.rfc5849.signature import (
normalize_base_string_uri,
normalize_parameters,
collect_parameters,
construct_base_string,
sign_hmac_sha1,
)
from social.backends.base import BaseAuth
from social.exceptions import AuthFailed
from social.utils import sanitize_redirect
log = logging.getLogger(__name__)
LTI_PARAMS_KEY = 'tpa-lti-params'
class LTIAuthBackend(BaseAuth):
"""
Third-party-auth module for Learning Tools Interoperability
"""
name = 'lti'
def start(self):
"""
Prepare to handle a login request.
This method replaces social.actions.do_auth and must be kept in sync
with any upstream changes in that method. In the current version of
the upstream, this means replacing the logic to populate the session
from request parameters, and not calling backend.start() to avoid
an unwanted redirect to the non-existent login page.
"""
# Clean any partial pipeline data
self.strategy.clean_partial_pipeline()
# Save validated LTI parameters (or None if invalid or not submitted)
validated_lti_params = self.get_validated_lti_params(self.strategy)
# Set a auth_entry here so we don't have to receive that as a custom parameter
self.strategy.session_setdefault('auth_entry', 'login')
if not validated_lti_params:
self.strategy.session_set(LTI_PARAMS_KEY, None)
raise AuthFailed(self, "LTI parameters could not be validated.")
else:
self.strategy.session_set(LTI_PARAMS_KEY, validated_lti_params)
# Save extra data into session.
# While Basic LTI 1.0 specifies that the message is to be signed using OAuth, implying
# that any GET parameters should be stripped from the base URL and included as signed
# parameters, typical LTI Tool Consumer implementations do not support this behaviour. As
# a workaround, we accept TPA parameters from LTI custom parameters prefixed with "tpa_".
for field_name in self.setting('FIELDS_STORED_IN_SESSION', []):
if 'custom_tpa_' + field_name in validated_lti_params:
self.strategy.session_set(field_name, validated_lti_params['custom_tpa_' + field_name])
if 'custom_tpa_' + REDIRECT_FIELD_NAME in validated_lti_params:
# Check and sanitize a user-defined GET/POST next field value
redirect_uri = validated_lti_params['custom_tpa_' + REDIRECT_FIELD_NAME]
if self.setting('SANITIZE_REDIRECTS', True):
redirect_uri = sanitize_redirect(self.strategy.request_host(), redirect_uri)
self.strategy.session_set(REDIRECT_FIELD_NAME, redirect_uri or self.setting('LOGIN_REDIRECT_URL'))
def auth_html(self):
"""
Not used
"""
raise NotImplementedError("Not used")
def auth_url(self):
"""
Not used
"""
raise NotImplementedError("Not used")
def auth_complete(self, *args, **kwargs):
"""
Completes third-part-auth authentication
"""
lti_params = self.strategy.session_get(LTI_PARAMS_KEY)
kwargs.update({'response': {LTI_PARAMS_KEY: lti_params}, 'backend': self})
return self.strategy.authenticate(*args, **kwargs)
def get_user_id(self, details, response):
"""
Computes social auth username from LTI parameters
"""
lti_params = response[LTI_PARAMS_KEY]
return lti_params['oauth_consumer_key'] + ":" + lti_params['user_id']
def get_user_details(self, response):
"""
Retrieves user details from LTI parameters
"""
details = {}
lti_params = response[LTI_PARAMS_KEY]
def add_if_exists(lti_key, details_key):
"""
Adds LTI parameter to user details dict if it exists
"""
if lti_key in lti_params and lti_params[lti_key]:
details[details_key] = lti_params[lti_key]
add_if_exists('email', 'email')
add_if_exists('lis_person_name_full', 'fullname')
add_if_exists('lis_person_name_given', 'first_name')
add_if_exists('lis_person_name_family', 'last_name')
return details
@classmethod
def get_validated_lti_params(cls, strategy):
"""
Validates LTI signature and returns LTI parameters
"""
request = Request(
uri=strategy.request.build_absolute_uri(), http_method=strategy.request.method, body=strategy.request.body
)
lti_consumer_key = request.oauth_consumer_key
(lti_consumer_valid, lti_consumer_secret, lti_max_timestamp_age) = cls.load_lti_consumer(lti_consumer_key)
current_time = calendar.timegm(time.gmtime())
return cls._get_validated_lti_params_from_values(
request=request, current_time=current_time,
lti_consumer_valid=lti_consumer_valid,
lti_consumer_secret=lti_consumer_secret,
lti_max_timestamp_age=lti_max_timestamp_age
)
@classmethod
def _get_validated_lti_params_from_values(cls, request, current_time,
lti_consumer_valid, lti_consumer_secret, lti_max_timestamp_age):
"""
Validates LTI signature and returns LTI parameters
"""
# Taking a cue from oauthlib, to avoid leaking information through a timing attack,
# we proceed through the entire validation before rejecting any request for any reason.
# However, as noted there, the value of doing this is dubious.
base_uri = normalize_base_string_uri(request.uri)
parameters = collect_parameters(uri_query=request.uri_query, body=request.body)
parameters_string = normalize_parameters(parameters)
base_string = construct_base_string(request.http_method, base_uri, parameters_string)
computed_signature = sign_hmac_sha1(base_string, unicode(lti_consumer_secret), '')
submitted_signature = request.oauth_signature
data = {parameter_value_pair[0]: parameter_value_pair[1] for parameter_value_pair in parameters}
def safe_int(value):
"""
Interprets parameter as an int or returns 0 if not possible
"""
try:
return int(value)
except (ValueError, TypeError):
return 0
oauth_timestamp = safe_int(request.oauth_timestamp)
# As this must take constant time, do not use shortcutting operators such as 'and'.
# Instead, use constant time operators such as '&', which is the bitwise and.
valid = (lti_consumer_valid)
valid = valid & (submitted_signature == computed_signature)
valid = valid & (request.oauth_version == '1.0')
valid = valid & (request.oauth_signature_method == 'HMAC-SHA1')
valid = valid & ('user_id' in data) # Not required by LTI but can't log in without one
valid = valid & (oauth_timestamp >= current_time - lti_max_timestamp_age)
valid = valid & (oauth_timestamp <= current_time)
if valid:
return data
else:
return None
@classmethod
def load_lti_consumer(cls, lti_consumer_key):
"""
Retrieves LTI consumer details from database
"""
from .models import LTIProviderConfig
provider_config = LTIProviderConfig.current(lti_consumer_key)
if provider_config and provider_config.enabled:
return (
provider_config.enabled,
provider_config.get_lti_consumer_secret(),
provider_config.lti_max_timestamp_age,
)
else:
return False, '', -1

View File

@@ -0,0 +1,149 @@
# -*- coding: utf-8 -*-
# pylint: disable=C,E,F,R,W
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'LTIProviderConfig'
db.create_table('third_party_auth_ltiproviderconfig', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('change_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('changed_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, on_delete=models.PROTECT)),
('enabled', self.gf('django.db.models.fields.BooleanField')(default=False)),
('icon_class', self.gf('django.db.models.fields.CharField')(default='fa-sign-in', max_length=50)),
('name', self.gf('django.db.models.fields.CharField')(max_length=50)),
('secondary', self.gf('django.db.models.fields.BooleanField')(default=False)),
('skip_registration_form', self.gf('django.db.models.fields.BooleanField')(default=False)),
('skip_email_verification', self.gf('django.db.models.fields.BooleanField')(default=False)),
('lti_consumer_key', self.gf('django.db.models.fields.CharField')(max_length=255)),
('lti_consumer_secret', self.gf('django.db.models.fields.CharField')(max_length=255)),
('lti_max_timestamp_age', self.gf('django.db.models.fields.IntegerField')(default=10)),
))
db.send_create_signal('third_party_auth', ['LTIProviderConfig'])
def backwards(self, orm):
# Deleting model 'LTIProviderConfig'
db.delete_table('third_party_auth_ltiproviderconfig')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'third_party_auth.ltiproviderconfig': {
'Meta': {'object_name': 'LTIProviderConfig'},
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'icon_class': ('django.db.models.fields.CharField', [], {'default': "'fa-sign-in'", 'max_length': '50'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lti_consumer_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'lti_consumer_secret': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'lti_max_timestamp_age': ('django.db.models.fields.IntegerField', [], {'default': '10'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'secondary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'skip_email_verification': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'skip_registration_form': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'third_party_auth.oauth2providerconfig': {
'Meta': {'object_name': 'OAuth2ProviderConfig'},
'backend_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'icon_class': ('django.db.models.fields.CharField', [], {'default': "'fa-sign-in'", 'max_length': '50'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'other_settings': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'secondary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'secret': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'skip_email_verification': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'skip_registration_form': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'third_party_auth.samlconfiguration': {
'Meta': {'object_name': 'SAMLConfiguration'},
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'entity_id': ('django.db.models.fields.CharField', [], {'default': "'http://saml.example.com'", 'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'org_info_str': ('django.db.models.fields.TextField', [], {'default': '\'{"en-US": {"url": "http://www.example.com", "displayname": "Example Inc.", "name": "example"}}\''}),
'other_config_str': ('django.db.models.fields.TextField', [], {'default': '\'{\\n"SECURITY_CONFIG": {"metadataCacheDuration": 604800, "signMetadata": false}\\n}\''}),
'private_key': ('django.db.models.fields.TextField', [], {}),
'public_key': ('django.db.models.fields.TextField', [], {})
},
'third_party_auth.samlproviderconfig': {
'Meta': {'object_name': 'SAMLProviderConfig'},
'attr_email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
'attr_first_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
'attr_full_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
'attr_last_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
'attr_user_permanent_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
'attr_username': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
'backend_name': ('django.db.models.fields.CharField', [], {'default': "'tpa-saml'", 'max_length': '50'}),
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'entity_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'icon_class': ('django.db.models.fields.CharField', [], {'default': "'fa-sign-in'", 'max_length': '50'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'idp_slug': ('django.db.models.fields.SlugField', [], {'max_length': '30'}),
'metadata_source': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'other_settings': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'secondary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'skip_email_verification': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'skip_registration_form': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'third_party_auth.samlproviderdata': {
'Meta': {'ordering': "('-fetched_at',)", 'object_name': 'SAMLProviderData'},
'entity_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'expires_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
'fetched_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'public_key': ('django.db.models.fields.TextField', [], {}),
'sso_url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
}
}
complete_apps = ['third_party_auth']

View File

@@ -3,6 +3,8 @@
Models used to implement SAML SSO support in third_party_auth
(inlcuding Shibboleth support)
"""
from __future__ import absolute_import
from config_models.models import ConfigurationModel, cache
from django.conf import settings
from django.core.exceptions import ValidationError
@@ -11,9 +13,11 @@ from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
import json
import logging
from provider.utils import long_token
from social.backends.base import BaseAuth
from social.backends.oauth import OAuthAuth
from social.backends.saml import SAMLAuth, SAMLIdentityProvider
from .lti import LTIAuthBackend, LTI_PARAMS_KEY
from social.exceptions import SocialAuthBaseException
from social.utils import module_member
@@ -32,6 +36,7 @@ def _load_backend_classes(base_class=BaseAuth):
_PSA_BACKENDS = {backend_class.name: backend_class for backend_class in _load_backend_classes()}
_PSA_OAUTH2_BACKENDS = [backend_class.name for backend_class in _load_backend_classes(OAuthAuth)]
_PSA_SAML_BACKENDS = [backend_class.name for backend_class in _load_backend_classes(SAMLAuth)]
_LTI_BACKENDS = [backend_class.name for backend_class in _load_backend_classes(LTIAuthBackend)]
def clean_json(value, of_type):
@@ -95,6 +100,7 @@ class ProviderConfig(ConfigurationModel):
)
prefix = None # used for provider_id. Set to a string value in subclass
backend_name = None # Set to a field or fixed value in subclass
accepts_logins = True # Whether to display a sign-in button when the provider is enabled
# "enabled" field is inherited from ConfigurationModel
@@ -454,3 +460,70 @@ class SAMLProviderData(models.Model):
cache.set(cls.cache_key_name(entity_id), current, cls.cache_timeout)
return current
class LTIProviderConfig(ProviderConfig):
"""
Configuration required for this edX instance to act as a LTI
Tool Provider and allow users to authenticate and be enrolled in a
course via third party LTI Tool Consumers.
"""
prefix = 'lti'
backend_name = 'lti'
icon_class = None # This provider is not visible to users
secondary = False # This provider is not visible to users
accepts_logins = False # LTI login cannot be initiated by the tool provider
KEY_FIELDS = ('lti_consumer_key', )
lti_consumer_key = models.CharField(
max_length=255,
help_text=(
'The name that the LTI Tool Consumer will use to identify itself'
)
)
lti_consumer_secret = models.CharField(
default=long_token,
max_length=255,
help_text=(
'The shared secret that the LTI Tool Consumer will use to '
'authenticate requests. Only this edX instance and this '
'tool consumer instance should know this value. '
'For increased security, you can avoid storing this in '
'your database by leaving this field blank and setting '
'SOCIAL_AUTH_LTI_CONSUMER_SECRETS = {"consumer key": "secret", ...} '
'in your instance\'s Django setttigs (or lms.auth.json)'
),
blank=True,
)
lti_max_timestamp_age = models.IntegerField(
default=10,
help_text=(
'The maximum age of oauth_timestamp values, in seconds.'
)
)
def match_social_auth(self, social_auth):
""" Is this provider being used for this UserSocialAuth entry? """
prefix = self.lti_consumer_key + ":"
return self.backend_name == social_auth.provider and social_auth.uid.startswith(prefix)
def is_active_for_pipeline(self, pipeline):
""" Is this provider being used for the specified pipeline? """
try:
return (
self.backend_name == pipeline['backend'] and
self.lti_consumer_key == pipeline['kwargs']['response'][LTI_PARAMS_KEY]['oauth_consumer_key']
)
except KeyError:
return False
def get_lti_consumer_secret(self):
""" If the LTI consumer secret is not stored in the database, check Django settings instead """
if self.lti_consumer_secret:
return self.lti_consumer_secret
return getattr(settings, 'SOCIAL_AUTH_LTI_CONSUMER_SECRETS', {}).get(self.lti_consumer_key, '')
class Meta(object): # pylint: disable=missing-docstring
verbose_name = "Provider Configuration (LTI)"
verbose_name_plural = verbose_name

View File

@@ -99,13 +99,6 @@ AUTH_ENTRY_LOGIN = 'login'
AUTH_ENTRY_REGISTER = 'register'
AUTH_ENTRY_ACCOUNT_SETTINGS = 'account_settings'
# This is left-over from an A/B test
# of the new combined login/registration page (ECOM-369)
# We need to keep both the old and new entry points
# until every session from before the test ended has expired.
AUTH_ENTRY_LOGIN_2 = 'account_login'
AUTH_ENTRY_REGISTER_2 = 'account_register'
# Entry modes into the authentication process by a remote API call (as opposed to a browser session).
AUTH_ENTRY_LOGIN_API = 'login_api'
AUTH_ENTRY_REGISTER_API = 'register_api'
@@ -126,28 +119,12 @@ AUTH_DISPATCH_URLS = {
AUTH_ENTRY_LOGIN: '/login',
AUTH_ENTRY_REGISTER: '/register',
AUTH_ENTRY_ACCOUNT_SETTINGS: '/account/settings',
# This is left-over from an A/B test
# of the new combined login/registration page (ECOM-369)
# We need to keep both the old and new entry points
# until every session from before the test ended has expired.
AUTH_ENTRY_LOGIN_2: '/account/login/',
AUTH_ENTRY_REGISTER_2: '/account/register/',
}
_AUTH_ENTRY_CHOICES = frozenset([
AUTH_ENTRY_LOGIN,
AUTH_ENTRY_REGISTER,
AUTH_ENTRY_ACCOUNT_SETTINGS,
# This is left-over from an A/B test
# of the new combined login/registration page (ECOM-369)
# We need to keep both the old and new entry points
# until every session from before the test ended has expired.
AUTH_ENTRY_LOGIN_2,
AUTH_ENTRY_REGISTER_2,
AUTH_ENTRY_LOGIN_API,
AUTH_ENTRY_REGISTER_API,
])
@@ -395,9 +372,10 @@ def get_provider_user_states(user):
if enabled_provider.match_social_auth(auth):
association_id = auth.id
break
states.append(
ProviderUserState(enabled_provider, user, association_id)
)
if enabled_provider.accepts_logins or association_id:
states.append(
ProviderUserState(enabled_provider, user, association_id)
)
return states
@@ -508,13 +486,13 @@ def ensure_user_information(strategy, auth_entry, backend=None, user=None, socia
if not user:
if auth_entry in [AUTH_ENTRY_LOGIN_API, AUTH_ENTRY_REGISTER_API]:
return HttpResponseBadRequest()
elif auth_entry in [AUTH_ENTRY_LOGIN, AUTH_ENTRY_LOGIN_2]:
elif auth_entry == AUTH_ENTRY_LOGIN:
# User has authenticated with the third party provider but we don't know which edX
# account corresponds to them yet, if any.
if should_force_account_creation():
return dispatch_to_register()
return dispatch_to_login()
elif auth_entry in [AUTH_ENTRY_REGISTER, AUTH_ENTRY_REGISTER_2]:
elif auth_entry == AUTH_ENTRY_REGISTER:
# User has authenticated with the third party provider and now wants to finish
# creating their edX account.
return dispatch_to_register()
@@ -603,7 +581,7 @@ def login_analytics(strategy, auth_entry, *args, **kwargs):
""" Sends login info to Segment.io """
event_name = None
if auth_entry in [AUTH_ENTRY_LOGIN, AUTH_ENTRY_LOGIN_2]:
if auth_entry == AUTH_ENTRY_LOGIN:
event_name = 'edx.bi.user.account.authenticated'
elif auth_entry in [AUTH_ENTRY_ACCOUNT_SETTINGS]:
event_name = 'edx.bi.user.account.linked'

View File

@@ -2,8 +2,8 @@
Third-party auth provider configuration API.
"""
from .models import (
OAuth2ProviderConfig, SAMLConfiguration, SAMLProviderConfig,
_PSA_OAUTH2_BACKENDS, _PSA_SAML_BACKENDS
OAuth2ProviderConfig, SAMLConfiguration, SAMLProviderConfig, LTIProviderConfig,
_PSA_OAUTH2_BACKENDS, _PSA_SAML_BACKENDS, _LTI_BACKENDS,
)
@@ -26,12 +26,21 @@ class Registry(object):
provider = SAMLProviderConfig.current(idp_slug)
if provider.enabled and provider.backend_name in _PSA_SAML_BACKENDS:
yield provider
for consumer_key in LTIProviderConfig.key_values('lti_consumer_key', flat=True):
provider = LTIProviderConfig.current(consumer_key)
if provider.enabled and provider.backend_name in _LTI_BACKENDS:
yield provider
@classmethod
def enabled(cls):
"""Returns list of enabled providers."""
return sorted(cls._enabled_providers(), key=lambda provider: provider.name)
@classmethod
def accepting_logins(cls):
"""Returns list of providers that can be used to initiate logins currently"""
return [provider for provider in cls.enabled() if provider.accepts_logins]
@classmethod
def get(cls, provider_id):
"""Gets provider by provider_id string if enabled, else None."""
@@ -83,3 +92,8 @@ class Registry(object):
provider = SAMLProviderConfig.current(idp_name)
if provider.backend_name == backend_name and provider.enabled:
yield provider
elif backend_name in _LTI_BACKENDS:
for consumer_key in LTIProviderConfig.key_values('lti_consumer_key', flat=True):
provider = LTIProviderConfig.current(consumer_key)
if provider.backend_name == backend_name and provider.enabled:
yield provider

View File

@@ -20,6 +20,8 @@ class ConfigurationModelStrategy(DjangoStrategy):
OAuthAuth subclasses will call this method for every setting they want to look up.
SAMLAuthBackend subclasses will call this method only after first checking if the
setting 'name' is configured via SAMLProviderConfig.
LTIAuthBackend subclasses will call this method only after first checking if the
setting 'name' is configured via LTIProviderConfig.
"""
if isinstance(backend, OAuthAuth):
provider_config = OAuth2ProviderConfig.current(backend.name)
@@ -29,6 +31,6 @@ class ConfigurationModelStrategy(DjangoStrategy):
return provider_config.get_setting(name)
except KeyError:
pass
# At this point, we know 'name' is not set in a [OAuth2|SAML]ProviderConfig row.
# At this point, we know 'name' is not set in a [OAuth2|LTI|SAML]ProviderConfig row.
# It's probably a global Django setting like 'FIELDS_STORED_IN_SESSION':
return super(ConfigurationModelStrategy, self).setting(name, default, backend)

View File

@@ -0,0 +1 @@
lti_message_type=basic-lti-launch-request&lti_version=LTI-1p0&lis_outcome_service_url=http%3A%2F%2Fwww.imsglobal.org%2Fdevelopers%2FLTI%2Ftest%2Fv1p1%2Fcommon%2Ftool_consumer_outcome.php%3Fb64%3DMTIzNDU6OjpzZWNyZXQ%3D&lis_result_sourcedid=feb-123-456-2929%3A%3A28883&launch_presentation_return_url=http%3A%2F%2Fwww.imsglobal.org%2Fdevelopers%2FLTI%2Ftest%2Fv1p1%2Flms_return.php&user_id=292832126&custom_extra=parameter&oauth_version=1.0&oauth_nonce=c4936a7122f4f85c2d95afe32391573b&oauth_timestamp=1436823553&oauth_consumer_key=12345&oauth_signature_method=HMAC-SHA1&oauth_signature=STPWUouDw%2FlRGD4giWf8lpGTc54%3D&oauth_callback=about%3Ablank

View File

@@ -0,0 +1 @@
some=garbage&values=provided

View File

@@ -0,0 +1 @@
lti_message_type=basic-lti-launch-request&lti_version=LTI-1p0&lis_outcome_service_url=http%3A%2F%2Fwww.imsglobal.org%2Fdevelopers%2FLTI%2Ftest%2Fv1p1%2Fcommon%2Ftool_consumer_outcome.php%3Fb64%3DMTIzNDU6OjpzZWNyZXQ%3D&lis_result_sourcedid=feb-123-456-2929%3A%3A28883&launch_presentation_return_url=http%3A%2F%2Fwww.imsglobal.org%2Fdevelopers%2FLTI%2Ftest%2Fv1p1%2Flms_return.php&user_id=292832126&custom_extra=parameter&oauth_version=1.0&oauth_nonce=c4936a7122f4f85c2d95afe32391573b&oauth_timestamp=1436823553&oauth_consumer_key=12345&oauth_signature_method=HMAC-SHA1&oauth_signature=STPWUouDw%2FlRGD4giWf8lpXXXXX%3D&oauth_callback=about%3Ablank

View File

@@ -0,0 +1 @@
lti_message_type=basic-lti-launch-request&lti_version=LTI-1p0&lis_outcome_service_url=http%3A%2F%2Fwww.imsglobal.org%2Fdevelopers%2FLTI%2Ftest%2Fv1p1%2Fcommon%2Ftool_consumer_outcome.php%3Fb64%3DMTIzNDU6OjpzZWNyZXQ%3D&lis_result_sourcedid=feb-123-456-2929%3A%3A28883&launch_presentation_return_url=http%3A%2F%2Fwww.imsglobal.org%2Fdevelopers%2FLTI%2Ftest%2Fv1p1%2Flms_return.php&user_id=292832126&custom_extra=parameter&oauth_version=1.0&oauth_nonce=c4936a7122f4f85c2d95afe32391573b&oauth_timestamp=1436823553&oauth_consumer_key=12345&oauth_signature_method=HMAC-SHA1&oauth_signature=STPWUouDw%2FlRGD4giWf8lpGTc54%3D&oauth_callback=about%3Ablank

View File

@@ -0,0 +1 @@
lti_message_type=basic-lti-launch-request&lti_version=LTI-1p0&lis_outcome_service_url=http%3A%2F%2Fwww.imsglobal.org%2Fdevelopers%2FLTI%2Ftest%2Fv1p1%2Fcommon%2Ftool_consumer_outcome.php%3Fb64%3DMTIzNDU6OjpzZWNyZXQ%3D&lis_result_sourcedid=feb-123-456-2929%3A%3A28883&launch_presentation_return_url=http%3A%2F%2Fwww.imsglobal.org%2Fdevelopers%2FLTI%2Ftest%2Fv1p1%2Flms_return.php&user_id=292832126&custom_extra=parameter&oauth_version=1.0&oauth_nonce=c4936a7122f4f85c2d95afe32391573b&oauth_timestamp=1436823553&oauth_consumer_key=12345&oauth_signature_method=HMAC-SHA1&oauth_signature=STPWUouDw%2FlRGD4giWf8lpGTc54%3D&oauth_callback=about%3Ablank

View File

@@ -0,0 +1 @@
lti_message_type=basic-lti-launch-request&lis_outcome_service_url=http%3A%2F%2Fwww.imsglobal.org%2Fdevelopers%2FLTI%2Ftest%2Fv1p1%2Fcommon%2Ftool_consumer_outcome.php%3Fb64%3DMTIzNDU6OjpzZWNyZXQ%3D&lis_result_sourcedid=feb-123-456-2929%3A%3A28883&launch_presentation_return_url=http%3A%2F%2Fwww.imsglobal.org%2Fdevelopers%2FLTI%2Ftest%2Fv1p1%2Flms_return.php&custom_extra=parameter&oauth_version=1.0&oauth_nonce=c4936a7122f4f85c2d95afe32391573b&oauth_timestamp=1436823553&oauth_consumer_key=12345&oauth_signature_method=HMAC-SHA1&oauth_signature=STPWUouDw%2FlRGD4giWf8lpGTc54%3D&oauth_callback=about%3Ablank

View File

@@ -381,12 +381,6 @@ class IntegrationTest(testutil.TestCase, test.TestCase):
def test_canceling_authentication_redirects_to_register_when_auth_entry_register(self):
self.assert_exception_redirect_looks_correct('/register', auth_entry=pipeline.AUTH_ENTRY_REGISTER)
def test_canceling_authentication_redirects_to_login_when_auth_login_2(self):
self.assert_exception_redirect_looks_correct('/account/login/', auth_entry=pipeline.AUTH_ENTRY_LOGIN_2)
def test_canceling_authentication_redirects_to_login_when_auth_register_2(self):
self.assert_exception_redirect_looks_correct('/account/register/', auth_entry=pipeline.AUTH_ENTRY_REGISTER_2)
def test_canceling_authentication_redirects_to_account_settings_when_auth_entry_account_settings(self):
self.assert_exception_redirect_looks_correct(
'/account/settings', auth_entry=pipeline.AUTH_ENTRY_ACCOUNT_SETTINGS

View File

@@ -0,0 +1,159 @@
"""
Integration tests for third_party_auth LTI auth providers
"""
import unittest
from django.conf import settings
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from oauthlib.oauth1.rfc5849 import Client, SIGNATURE_TYPE_BODY
from third_party_auth.tests import testutil
FORM_ENCODED = 'application/x-www-form-urlencoded'
LTI_CONSUMER_KEY = 'consumer'
LTI_CONSUMER_SECRET = 'secret'
LTI_TPA_LOGIN_URL = 'http://testserver/auth/login/lti/'
LTI_TPA_COMPLETE_URL = 'http://testserver/auth/complete/lti/'
OTHER_LTI_CONSUMER_KEY = 'settings-consumer'
OTHER_LTI_CONSUMER_SECRET = 'secret2'
LTI_USER_ID = 'lti_user_id'
EDX_USER_ID = 'test_user'
EMAIL = 'lti_user@example.com'
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class IntegrationTestLTI(testutil.TestCase):
"""
Integration tests for third_party_auth LTI auth providers
"""
def setUp(self):
super(IntegrationTestLTI, self).setUp()
self.configure_lti_provider(
name='Other Tool Consumer 1', enabled=True,
lti_consumer_key='other1',
lti_consumer_secret='secret1',
lti_max_timestamp_age=10,
)
self.configure_lti_provider(
name='LTI Test Tool Consumer', enabled=True,
lti_consumer_key=LTI_CONSUMER_KEY,
lti_consumer_secret=LTI_CONSUMER_SECRET,
lti_max_timestamp_age=10,
)
self.configure_lti_provider(
name='Tool Consumer with Secret in Settings', enabled=True,
lti_consumer_key=OTHER_LTI_CONSUMER_KEY,
lti_consumer_secret='',
lti_max_timestamp_age=10,
)
self.lti = Client(
client_key=LTI_CONSUMER_KEY,
client_secret=LTI_CONSUMER_SECRET,
signature_type=SIGNATURE_TYPE_BODY,
)
def test_lti_login(self):
# The user initiates a login from an external site
(uri, _headers, body) = self.lti.sign(
uri=LTI_TPA_LOGIN_URL, http_method='POST',
headers={'Content-Type': FORM_ENCODED},
body={
'user_id': LTI_USER_ID,
'custom_tpa_next': '/account/finish_auth/?course_id=my_course_id&enrollment_action=enroll',
}
)
login_response = self.client.post(path=uri, content_type=FORM_ENCODED, data=body)
# The user should be redirected to the registration form
self.assertEqual(login_response.status_code, 302)
self.assertTrue(login_response['Location'].endswith(reverse('signin_user')))
register_response = self.client.get(login_response['Location'])
self.assertEqual(register_response.status_code, 200)
self.assertIn('currentProvider&#34;: &#34;LTI Test Tool Consumer&#34;', register_response.content)
self.assertIn('&#34;errorMessage&#34;: null', register_response.content)
# Now complete the form:
ajax_register_response = self.client.post(
reverse('user_api_registration'),
{
'email': EMAIL,
'name': 'Myself',
'username': EDX_USER_ID,
'honor_code': True,
}
)
self.assertEqual(ajax_register_response.status_code, 200)
continue_response = self.client.get(LTI_TPA_COMPLETE_URL)
# The user should be redirected to the finish_auth view which will enroll them.
# FinishAuthView.js reads the URL parameters directly from $.url
self.assertEqual(continue_response.status_code, 302)
self.assertEqual(
continue_response['Location'],
'http://testserver/account/finish_auth/?course_id=my_course_id&enrollment_action=enroll'
)
# Now check that we can login again
self.client.logout()
self.verify_user_email(EMAIL)
(uri, _headers, body) = self.lti.sign(
uri=LTI_TPA_LOGIN_URL, http_method='POST',
headers={'Content-Type': FORM_ENCODED},
body={'user_id': LTI_USER_ID}
)
login_2_response = self.client.post(path=uri, content_type=FORM_ENCODED, data=body)
# The user should be redirected to the dashboard
self.assertEqual(login_2_response.status_code, 302)
self.assertEqual(login_2_response['Location'], LTI_TPA_COMPLETE_URL)
continue_2_response = self.client.get(login_2_response['Location'])
self.assertEqual(continue_2_response.status_code, 302)
self.assertTrue(continue_2_response['Location'].endswith(reverse('dashboard')))
# Check that the user was created correctly
user = User.objects.get(email=EMAIL)
self.assertEqual(user.username, EDX_USER_ID)
def test_reject_initiating_login(self):
response = self.client.get(LTI_TPA_LOGIN_URL)
self.assertEqual(response.status_code, 405) # Not Allowed
def test_reject_bad_login(self):
login_response = self.client.post(
path=LTI_TPA_LOGIN_URL, content_type=FORM_ENCODED,
data="invalid=login"
)
# The user should be redirected to the login page with an error message
# (auth_entry defaults to login for this provider)
self.assertEqual(login_response.status_code, 302)
self.assertTrue(login_response['Location'].endswith(reverse('signin_user')))
error_response = self.client.get(login_response['Location'])
self.assertIn(
'Authentication failed: LTI parameters could not be validated.',
error_response.content
)
def test_can_load_consumer_secret_from_settings(self):
lti = Client(
client_key=OTHER_LTI_CONSUMER_KEY,
client_secret=OTHER_LTI_CONSUMER_SECRET,
signature_type=SIGNATURE_TYPE_BODY,
)
(uri, _headers, body) = lti.sign(
uri=LTI_TPA_LOGIN_URL, http_method='POST',
headers={'Content-Type': FORM_ENCODED},
body={
'user_id': LTI_USER_ID,
'custom_tpa_next': '/account/finish_auth/?course_id=my_course_id&enrollment_action=enroll',
}
)
with self.settings(SOCIAL_AUTH_LTI_CONSUMER_SECRETS={OTHER_LTI_CONSUMER_KEY: OTHER_LTI_CONSUMER_SECRET}):
login_response = self.client.post(path=uri, content_type=FORM_ENCODED, data=body)
# The user should be redirected to the registration form
self.assertEqual(login_response.status_code, 302)
self.assertTrue(login_response['Location'].endswith(reverse('signin_user')))
register_response = self.client.get(login_response['Location'])
self.assertEqual(register_response.status_code, 200)
self.assertIn(
'currentProvider&#34;: &#34;Tool Consumer with Secret in Settings&#34;',
register_response.content
)
self.assertIn('&#34;errorMessage&#34;: null', register_response.content)

View File

@@ -1,7 +1,6 @@
"""
Third_party_auth integration tests using a mock version of the TestShib provider
"""
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
import httpretty
from mock import patch
@@ -38,7 +37,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
def metadata_callback(_request, _uri, headers):
""" Return a cached copy of TestShib's metadata by reading it from disk """
return (200, headers, self._read_data_file('testshib_metadata.xml'))
return (200, headers, self.read_data_file('testshib_metadata.xml'))
httpretty.register_uri(httpretty.GET, TESTSHIB_METADATA_URL, content_type='text/xml', body=metadata_callback)
self.addCleanup(httpretty.disable)
self.addCleanup(httpretty.reset)
@@ -106,7 +105,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
# Now check that we can login again:
self.client.logout()
self._verify_user_email('myself@testshib.org')
self.verify_user_email('myself@testshib.org')
self._test_return_login()
def test_login(self):
@@ -220,11 +219,5 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
return self.client.post(
TPA_TESTSHIB_COMPLETE_URL,
content_type='application/x-www-form-urlencoded',
data=self._read_data_file('testshib_response.txt'),
data=self.read_data_file('testshib_response.txt'),
)
def _verify_user_email(self, email):
""" Mark the user with the given email as verified """
user = User.objects.get(email=email)
user.is_active = True
user.save()

View File

@@ -0,0 +1,133 @@
"""
Unit tests for third_party_auth LTI auth providers
"""
import unittest
from oauthlib.common import Request
from third_party_auth.lti import LTIAuthBackend, LTI_PARAMS_KEY
from third_party_auth.tests.testutil import ThirdPartyAuthTestMixin
class UnitTestLTI(unittest.TestCase, ThirdPartyAuthTestMixin):
"""
Unit tests for third_party_auth LTI auth providers
"""
def test_get_user_details_missing_keys(self):
lti = LTIAuthBackend()
details = lti.get_user_details({LTI_PARAMS_KEY: {
'lis_person_name_full': 'Full name'
}})
self.assertEquals(details, {
'fullname': 'Full name'
})
def test_get_user_details_extra_keys(self):
lti = LTIAuthBackend()
details = lti.get_user_details({LTI_PARAMS_KEY: {
'lis_person_name_full': 'Full name',
'lis_person_name_given': 'Given',
'lis_person_name_family': 'Family',
'email': 'user@example.com',
'other': 'something else'
}})
self.assertEquals(details, {
'fullname': 'Full name',
'first_name': 'Given',
'last_name': 'Family',
'email': 'user@example.com'
})
def test_get_user_id(self):
lti = LTIAuthBackend()
user_id = lti.get_user_id(None, {LTI_PARAMS_KEY: {
'oauth_consumer_key': 'consumer',
'user_id': 'user'
}})
self.assertEquals(user_id, 'consumer:user')
def test_validate_lti_valid_request(self):
request = Request(
uri='https://example.com/lti',
http_method='POST',
body=self.read_data_file('lti_valid_request.txt')
)
parameters = LTIAuthBackend._get_validated_lti_params_from_values( # pylint: disable=protected-access
request=request, current_time=1436823554,
lti_consumer_valid=True, lti_consumer_secret='secret',
lti_max_timestamp_age=10
)
self.assertTrue(parameters)
self.assertDictContainsSubset({
'custom_extra': 'parameter',
'user_id': '292832126'
}, parameters)
def test_validate_lti_valid_request_with_get_params(self):
request = Request(
uri='https://example.com/lti?user_id=292832126&lti_version=LTI-1p0',
http_method='POST',
body=self.read_data_file('lti_valid_request_with_get_params.txt')
)
parameters = LTIAuthBackend._get_validated_lti_params_from_values( # pylint: disable=protected-access
request=request, current_time=1436823554,
lti_consumer_valid=True, lti_consumer_secret='secret',
lti_max_timestamp_age=10
)
self.assertTrue(parameters)
self.assertDictContainsSubset({
'custom_extra': 'parameter',
'user_id': '292832126'
}, parameters)
def test_validate_lti_old_timestamp(self):
request = Request(
uri='https://example.com/lti',
http_method='POST',
body=self.read_data_file('lti_old_timestamp.txt')
)
parameters = LTIAuthBackend._get_validated_lti_params_from_values( # pylint: disable=protected-access
request=request, current_time=1436900000,
lti_consumer_valid=True, lti_consumer_secret='secret',
lti_max_timestamp_age=10
)
self.assertFalse(parameters)
def test_validate_lti_invalid_signature(self):
request = Request(
uri='https://example.com/lti',
http_method='POST',
body=self.read_data_file('lti_invalid_signature.txt')
)
parameters = LTIAuthBackend._get_validated_lti_params_from_values( # pylint: disable=protected-access
request=request, current_time=1436823554,
lti_consumer_valid=True, lti_consumer_secret='secret',
lti_max_timestamp_age=10
)
self.assertFalse(parameters)
def test_validate_lti_cannot_add_get_params(self):
request = Request(
uri='https://example.com/lti?custom_another=parameter',
http_method='POST',
body=self.read_data_file('lti_cannot_add_get_params.txt')
)
parameters = LTIAuthBackend._get_validated_lti_params_from_values( # pylint: disable=protected-access
request=request, current_time=1436823554,
lti_consumer_valid=True, lti_consumer_secret='secret',
lti_max_timestamp_age=10
)
self.assertFalse(parameters)
def test_validate_lti_garbage(self):
request = Request(
uri='https://example.com/lti',
http_method='POST',
body=self.read_data_file('lti_garbage.txt')
)
parameters = LTIAuthBackend._get_validated_lti_params_from_values( # pylint: disable=protected-access
request=request, current_time=1436823554,
lti_consumer_valid=True, lti_consumer_secret='secret',
lti_max_timestamp_age=10
)
self.assertFalse(parameters)

View File

@@ -6,11 +6,18 @@ Used by Django and non-Django tests; must not have Django deps.
from contextlib import contextmanager
from django.conf import settings
from django.contrib.auth.models import User
import django.test
import mock
import os.path
from third_party_auth.models import OAuth2ProviderConfig, SAMLProviderConfig, SAMLConfiguration, cache as config_cache
from third_party_auth.models import (
OAuth2ProviderConfig,
SAMLProviderConfig,
SAMLConfiguration,
LTIProviderConfig,
cache as config_cache,
)
AUTH_FEATURES_KEY = 'ENABLE_THIRD_PARTY_AUTH'
@@ -52,6 +59,13 @@ class ThirdPartyAuthTestMixin(object):
obj.save()
return obj
@staticmethod
def configure_lti_provider(**kwargs):
""" Update the settings for a LTI Tool Consumer third party auth provider """
obj = LTIProviderConfig(**kwargs)
obj.save()
return obj
@classmethod
def configure_google_provider(cls, **kwargs):
""" Update the settings for the Google third party auth provider/backend """
@@ -92,6 +106,19 @@ class ThirdPartyAuthTestMixin(object):
kwargs.setdefault("secret", "test")
return cls.configure_oauth_provider(**kwargs)
@classmethod
def verify_user_email(cls, email):
""" Mark the user with the given email as verified """
user = User.objects.get(email=email)
user.is_active = True
user.save()
@staticmethod
def read_data_file(filename):
""" Read the contents of a file in the data folder """
with open(os.path.join(os.path.dirname(__file__), 'data', filename)) as f:
return f.read()
class TestCase(ThirdPartyAuthTestMixin, django.test.TestCase):
"""Base class for auth test cases."""
@@ -111,18 +138,12 @@ class SAMLTestCase(TestCase):
@classmethod
def _get_public_key(cls, key_name='saml_key'):
""" Get a public key for use in the test. """
return cls._read_data_file('{}.pub'.format(key_name))
return cls.read_data_file('{}.pub'.format(key_name))
@classmethod
def _get_private_key(cls, key_name='saml_key'):
""" Get a private key for use in the test. """
return cls._read_data_file('{}.key'.format(key_name))
@staticmethod
def _read_data_file(filename):
""" Read the contents of a file in the data folder """
with open(os.path.join(os.path.dirname(__file__), 'data', filename)) as f:
return f.read()
return cls.read_data_file('{}.key'.format(key_name))
def enable_saml(self, **kwargs):
""" Enable SAML support (via SAMLConfiguration, not for any particular provider) """

View File

@@ -2,11 +2,12 @@
from django.conf.urls import include, patterns, url
from .views import inactive_user_view, saml_metadata_view
from .views import inactive_user_view, saml_metadata_view, lti_login_and_complete_view
urlpatterns = patterns(
'',
url(r'^auth/inactive', inactive_user_view),
url(r'^auth/saml/metadata.xml', saml_metadata_view),
url(r'^auth/login/(?P<backend>lti)/$', lti_login_and_complete_view),
url(r'^auth/', include('social.apps.django_app.urls', namespace='social')),
)

View File

@@ -3,11 +3,17 @@ Extra views required for SSO
"""
from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseServerError, Http404
from django.http import HttpResponse, HttpResponseServerError, Http404, HttpResponseNotAllowed
from django.shortcuts import redirect
from django.views.decorators.csrf import csrf_exempt
import social
from social.apps.django_app.views import complete
from social.apps.django_app.utils import load_strategy, load_backend
from social.utils import setting_name
from .models import SAMLConfiguration
URL_NAMESPACE = getattr(settings, setting_name('URL_NAMESPACE'), None) or 'social'
def inactive_user_view(request):
"""
@@ -36,3 +42,15 @@ def saml_metadata_view(request):
if not errors:
return HttpResponse(content=metadata, content_type='text/xml')
return HttpResponseServerError(content=', '.join(errors))
@csrf_exempt
@social.apps.django_app.utils.psa('{0}:complete'.format(URL_NAMESPACE))
def lti_login_and_complete_view(request, backend, *args, **kwargs):
"""This is a combination login/complete due to LTI being a one step login"""
if request.method != 'POST':
return HttpResponseNotAllowed('POST')
request.backend.start()
return complete(request, backend, *args, **kwargs)

View File

@@ -60,6 +60,7 @@ lib_paths:
- public/js/split_test_staff.js
- common_static/js/src/accessibility_tools.js
- common_static/js/vendor/moment.min.js
- spec/main_requirejs.js
# Paths to spec (test) JavaScript files
spec_paths:

View File

@@ -0,0 +1,11 @@
(function(requirejs) {
requirejs.config({
paths: {
"moment": "xmodule/include/common_static/js/vendor/moment.min"
},
"moment": {
exports: "moment"
}
});
}).call(this, RequireJS.requirejs);

View File

@@ -14,10 +14,9 @@
define(
'video/01_initialize.js',
['video/03_video_player.js', 'video/00_i18n.js'],
function (VideoPlayer, i18n) {
var moment = window.moment;
['video/03_video_player.js', 'video/00_i18n.js', 'moment'],
function (VideoPlayer, i18n, moment) {
var moment = moment || window.moment;
/**
* @function
*

View File

@@ -280,21 +280,6 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
courses[course_id] = course
return courses.values()
@strip_key
def get_courses_keys(self, **kwargs):
'''
Returns a list containing the top level XModuleDescriptors keys of the courses in this modulestore.
'''
courses = {}
for store in self.modulestores:
# filter out ones which were fetched from earlier stores but locations may not be ==
for course in store.get_courses(**kwargs):
course_id = self._clean_locator_for_mapping(course.id)
if course_id not in courses:
# course is indeed unique. save it in result
courses[course_id] = course
return courses.keys()
@strip_key
def get_libraries(self, **kwargs):
"""

View File

@@ -30,6 +30,8 @@
isZeroIndexed: false,
perPage: 10,
isStale: false,
sortField: '',
sortDirection: 'descending',
sortableFields: {},
@@ -37,6 +39,8 @@
filterField: '',
filterableFields: {},
searchString: null,
paginator_core: {
type: 'GET',
dataType: 'json',
@@ -51,9 +55,10 @@
},
server_api: {
'page': function () { return this.currentPage; },
'page_size': function () { return this.perPage; },
'sort_order': function () { return this.sortField; }
page: function () { return this.currentPage; },
page_size: function () { return this.perPage; },
text_search: function () { return this.searchString ? this.searchString : ''; },
sort_order: function () { return this.sortField; }
},
parse: function (response) {
@@ -61,7 +66,11 @@
this.currentPage = response.current_page;
this.totalPages = response.num_pages;
this.start = response.start;
this.sortField = response.sort_order;
// Note: sort_order is not returned when performing a search
if (response.sort_order) {
this.sortField = response.sort_order;
}
return response.results;
},
@@ -84,6 +93,7 @@
self = this;
return this.goTo(page - (this.isZeroIndexed ? 1 : 0), {reset: true}).then(
function () {
self.isStale = false;
self.trigger('page_changed');
},
function () {
@@ -92,6 +102,24 @@
);
},
/**
* Refreshes the collection if it has been marked as stale.
* @returns {promise} Returns a promise representing the refresh.
*/
refresh: function() {
var deferred = $.Deferred();
if (this.isStale) {
this.setPage(1)
.done(function() {
deferred.resolve();
});
} else {
deferred.resolve();
}
return deferred.promise();
},
/**
* Returns true if the collection has a next page, false otherwise.
*/
@@ -183,7 +211,7 @@
}
}
this.sortField = fieldName;
this.setPage(1);
this.isStale = true;
},
/**
@@ -193,7 +221,7 @@
*/
setSortDirection: function (direction) {
this.sortDirection = direction;
this.setPage(1);
this.isStale = true;
},
/**
@@ -203,7 +231,19 @@
*/
setFilterField: function (fieldName) {
this.filterField = fieldName;
this.setPage(1);
this.isStale = true;
},
/**
* Sets the string to use for a text search. If no string is specified then
* the search is cleared.
* @param searchString A string to search on, or null if no search is to be applied.
*/
setSearchString: function(searchString) {
if (searchString !== this.searchString) {
this.searchString = searchString;
this.isStale = true;
}
}
}, {
SortDirection: {

View File

@@ -43,10 +43,16 @@
return this;
},
/**
* Updates the collection's sort order, and fetches an updated set of
* results.
* @returns {*} A promise for the collection being updated
*/
sortCollection: function () {
var selected = this.$('#paging-header-select option:selected');
this.sortOrder = selected.attr('value');
this.collection.setSortField(this.sortOrder);
return this.collection.refresh();
}
});
return PagingHeader;

View File

@@ -0,0 +1,71 @@
/**
* A search field that works in concert with a paginated collection. When the user
* performs a search, the collection's search string will be updated and then the
* collection will be refreshed to show the first page of results.
*/
;(function (define) {
'use strict';
define(['backbone', 'jquery', 'underscore', 'text!common/templates/components/search-field.underscore'],
function (Backbone, $, _, searchFieldTemplate) {
return Backbone.View.extend({
events: {
'submit .search-form': 'performSearch',
'blur .search-form': 'onFocusOut',
'keyup .search-field': 'refreshState',
'click .action-clear': 'clearSearch'
},
initialize: function(options) {
this.type = options.type;
this.label = options.label;
},
refreshState: function() {
var searchField = this.$('.search-field'),
clearButton = this.$('.action-clear'),
searchString = $.trim(searchField.val());
if (searchString) {
clearButton.removeClass('is-hidden');
} else {
clearButton.addClass('is-hidden');
}
},
render: function() {
this.$el.html(_.template(searchFieldTemplate, {
type: this.type,
searchString: this.collection.searchString,
searchLabel: this.label
}));
this.refreshState();
return this;
},
onFocusOut: function(event) {
// If the focus is going anywhere but the clear search
// button then treat it as a request to search.
if (!$(event.relatedTarget).hasClass('action-clear')) {
this.performSearch(event);
}
},
performSearch: function(event) {
var searchField = this.$('.search-field'),
searchString = $.trim(searchField.val());
event.preventDefault();
this.collection.setSearchString(searchString);
return this.collection.refresh();
},
clearSearch: function(event) {
event.preventDefault();
this.$('.search-field').val('');
this.collection.setSearchString('');
this.refreshState();
return this.collection.refresh();
}
});
});
}).call(this, define || RequireJS.define);

View File

@@ -10,11 +10,11 @@ define(['jquery',
'use strict';
describe('PagingCollection', function () {
var collection, requests, server, assertQueryParams;
server = {
var collection;
var server = {
isZeroIndexed: false,
count: 43,
respond: function () {
respond: function (requests) {
var params = (new URI(requests[requests.length - 1].url)).query(true),
page = parseInt(params['page'], 10),
page_size = parseInt(params['page_size'], 10),
@@ -35,7 +35,7 @@ define(['jquery',
}
}
};
assertQueryParams = function (params) {
var assertQueryParams = function (requests, params) {
var urlParams = (new URI(requests[requests.length - 1].url)).query(true);
_.each(params, function (value, key) {
expect(urlParams[key]).toBe(value);
@@ -45,7 +45,6 @@ define(['jquery',
beforeEach(function () {
collection = new PagingCollection();
collection.perPage = 10;
requests = AjaxHelpers.requests(this);
server.isZeroIndexed = false;
server.count = 43;
});
@@ -69,10 +68,11 @@ define(['jquery',
});
it('can set the sort field', function () {
var requests = AjaxHelpers.requests(this);
collection.registerSortableField('test_field', 'Test Field');
collection.setSortField('test_field', false);
expect(requests.length).toBe(1);
assertQueryParams({'sort_order': 'test_field'});
collection.refresh();
assertQueryParams(requests, {'sort_order': 'test_field'});
expect(collection.sortField).toBe('test_field');
expect(collection.sortDisplayName()).toBe('Test Field');
});
@@ -80,7 +80,7 @@ define(['jquery',
it('can set the filter field', function () {
collection.registerFilterableField('test_field', 'Test Field');
collection.setFilterField('test_field');
expect(requests.length).toBe(1);
collection.refresh();
// The default implementation does not send any query params for filtering
expect(collection.filterField).toBe('test_field');
expect(collection.filterDisplayName()).toBe('Test Field');
@@ -88,11 +88,9 @@ define(['jquery',
it('can set the sort direction', function () {
collection.setSortDirection(PagingCollection.SortDirection.ASCENDING);
expect(requests.length).toBe(1);
// The default implementation does not send any query params for sort direction
expect(collection.sortDirection).toBe(PagingCollection.SortDirection.ASCENDING);
collection.setSortDirection(PagingCollection.SortDirection.DESCENDING);
expect(requests.length).toBe(2);
expect(collection.sortDirection).toBe(PagingCollection.SortDirection.DESCENDING);
});
@@ -113,11 +111,12 @@ define(['jquery',
'queries with page, page_size, and sort_order parameters when zero indexed': [true, 2],
'queries with page, page_size, and sort_order parameters when one indexed': [false, 3],
}, function (isZeroIndexed, page) {
var requests = AjaxHelpers.requests(this);
collection.isZeroIndexed = isZeroIndexed;
collection.perPage = 5;
collection.sortField = 'test_field';
collection.setPage(3);
assertQueryParams({'page': page.toString(), 'page_size': '5', 'sort_order': 'test_field'});
assertQueryParams(requests, {'page': page.toString(), 'page_size': '5', 'sort_order': 'test_field'});
});
SpecHelpers.withConfiguration({
@@ -129,27 +128,30 @@ define(['jquery',
}, function () {
describe('setPage', function() {
it('triggers a reset event when the page changes successfully', function () {
var resetTriggered = false;
var requests = AjaxHelpers.requests(this),
resetTriggered = false;
collection.on('reset', function () { resetTriggered = true; });
collection.setPage(3);
server.respond();
server.respond(requests);
expect(resetTriggered).toBe(true);
});
it('triggers an error event when the requested page is out of range', function () {
var errorTriggered = false;
var requests = AjaxHelpers.requests(this),
errorTriggered = false;
collection.on('error', function () { errorTriggered = true; });
collection.setPage(17);
server.respond();
server.respond(requests);
expect(errorTriggered).toBe(true);
});
it('triggers an error event if the server responds with a 500', function () {
var errorTriggered = false;
var requests = AjaxHelpers.requests(this),
errorTriggered = false;
collection.on('error', function () { errorTriggered = true; });
collection.setPage(2);
expect(collection.getPage()).toBe(2);
server.respond();
server.respond(requests);
collection.setPage(3);
AjaxHelpers.respondWithError(requests, 500, {}, requests.length - 1);
expect(errorTriggered).toBe(true);
@@ -159,11 +161,12 @@ define(['jquery',
describe('getPage', function () {
it('returns the correct page', function () {
var requests = AjaxHelpers.requests(this);
collection.setPage(1);
server.respond();
server.respond(requests);
expect(collection.getPage()).toBe(1);
collection.setPage(3);
server.respond();
server.respond(requests);
expect(collection.getPage()).toBe(3);
});
});
@@ -177,9 +180,10 @@ define(['jquery',
'returns false on the last page': [5, 43, false]
},
function (page, count, result) {
var requests = AjaxHelpers.requests(this);
server.count = count;
collection.setPage(page);
server.respond();
server.respond(requests);
expect(collection.hasNextPage()).toBe(result);
}
);
@@ -194,9 +198,10 @@ define(['jquery',
'returns false on the first page': [1, 43, false]
},
function (page, count, result) {
var requests = AjaxHelpers.requests(this);
server.count = count;
collection.setPage(page);
server.respond();
server.respond(requests);
expect(collection.hasPreviousPage()).toBe(result);
}
);
@@ -209,13 +214,14 @@ define(['jquery',
'silently fails on the last page': [5, 43, 5]
},
function (page, count, newPage) {
var requests = AjaxHelpers.requests(this);
server.count = count;
collection.setPage(page);
server.respond();
server.respond(requests);
expect(collection.getPage()).toBe(page);
collection.nextPage();
if (requests.length > 1) {
server.respond();
server.respond(requests);
}
expect(collection.getPage()).toBe(newPage);
}
@@ -229,13 +235,14 @@ define(['jquery',
'silently fails on the first page': [1, 43, 1]
},
function (page, count, newPage) {
var requests = AjaxHelpers.requests(this);
server.count = count;
collection.setPage(page);
server.respond();
server.respond(requests);
expect(collection.getPage()).toBe(page);
collection.previousPage();
if (requests.length > 1) {
server.respond();
server.respond(requests);
}
expect(collection.getPage()).toBe(newPage);
}

View File

@@ -0,0 +1,105 @@
define([
'underscore',
'common/js/components/views/search_field',
'common/js/components/collections/paging_collection',
'common/js/spec_helpers/ajax_helpers'
], function (_, SearchFieldView, PagingCollection, AjaxHelpers) {
'use strict';
describe('SearchFieldView', function () {
var searchFieldView,
mockUrl = '/api/mock_collection';
var newCollection = function (size, perPage) {
var pageSize = 5,
results = _.map(_.range(size), function (i) { return {foo: i}; });
var collection = new PagingCollection(
[],
{
url: mockUrl,
count: results.length,
num_pages: results.length / pageSize,
current_page: 1,
start: 0,
results: _.first(results, perPage)
},
{parse: true}
);
collection.start = 0;
collection.totalCount = results.length;
return collection;
};
var createSearchFieldView = function (options) {
options = _.extend(
{
type: 'test',
collection: newCollection(5, 4),
el: $('.test-search')
},
options || {}
);
return new SearchFieldView(options);
};
beforeEach(function() {
setFixtures('<section class="test-search"></section>');
});
it('correctly displays itself', function () {
searchFieldView = createSearchFieldView().render();
expect(searchFieldView.$('.search-field').val(), '');
expect(searchFieldView.$('.action-clear')).toHaveClass('is-hidden');
});
it('can display with an initial search string', function () {
searchFieldView = createSearchFieldView({
searchString: 'foo'
}).render();
expect(searchFieldView.$('.search-field').val(), 'foo');
});
it('refreshes the collection when performing a search', function () {
var requests = AjaxHelpers.requests(this);
searchFieldView = createSearchFieldView().render();
searchFieldView.$('.search-field').val('foo');
searchFieldView.$('.action-search').click();
AjaxHelpers.expectRequestURL(requests, mockUrl, {
page: '1',
page_size: '10',
sort_order: '',
text_search: 'foo'
});
AjaxHelpers.respondWithJson(requests, {
count: 10,
current_page: 1,
num_pages: 1,
start: 0,
results: []
});
expect(searchFieldView.$('.search-field').val(), 'foo');
});
it('can clear the search', function () {
var requests = AjaxHelpers.requests(this);
searchFieldView = createSearchFieldView({
searchString: 'foo'
}).render();
searchFieldView.$('.action-clear').click();
AjaxHelpers.expectRequestURL(requests, mockUrl, {
page: '1',
page_size: '10',
sort_order: '',
text_search: ''
});
AjaxHelpers.respondWithJson(requests, {
count: 10,
current_page: 1,
num_pages: 1,
start: 0,
results: []
});
expect(searchFieldView.$('.search-field').val(), '');
expect(searchFieldView.$('.action-clear')).toHaveClass('is-hidden');
});
});
});

View File

@@ -1,7 +1,7 @@
define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) {
'use strict';
var fakeServer, fakeRequests, expectRequest, expectJsonRequest, expectPostRequest, expectJsonRequestURL,
var fakeServer, fakeRequests, expectRequest, expectJsonRequest, expectPostRequest, expectRequestURL,
respondWithJson, respondWithError, respondWithTextError, respondWithNoContent;
/* These utility methods are used by Jasmine tests to create a mock server or
@@ -77,7 +77,7 @@ define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) {
* @param expectedParameters An object representing the URL parameters
* @param requestIndex An optional index for the request (by default, the last request is used)
*/
expectJsonRequestURL = function(requests, expectedUrl, expectedParameters, requestIndex) {
expectRequestURL = function(requests, expectedUrl, expectedParameters, requestIndex) {
var request, parameters;
if (_.isUndefined(requestIndex)) {
requestIndex = requests.length - 1;
@@ -153,15 +153,15 @@ define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) {
};
return {
'server': fakeServer,
'requests': fakeRequests,
'expectRequest': expectRequest,
'expectJsonRequest': expectJsonRequest,
'expectJsonRequestURL': expectJsonRequestURL,
'expectPostRequest': expectPostRequest,
'respondWithJson': respondWithJson,
'respondWithError': respondWithError,
'respondWithTextError': respondWithTextError,
'respondWithNoContent': respondWithNoContent,
server: fakeServer,
requests: fakeRequests,
expectRequest: expectRequest,
expectJsonRequest: expectJsonRequest,
expectPostRequest: expectPostRequest,
expectRequestURL: expectRequestURL,
respondWithJson: respondWithJson,
respondWithError: respondWithError,
respondWithTextError: respondWithTextError,
respondWithNoContent: respondWithNoContent
};
});

View File

@@ -0,0 +1,12 @@
<div class="page-header-search wrapper-search-<%= type %>">
<form class="search-form">
<div class="wrapper-search-input">
<label for="search-<%= type %>" class="search-label">><%- searchLabel %></label>
<input id="search-<%= type %>" class="search-field" type="text" value="<%- searchString %>" placeholder="<%- searchLabel %>" />
<button type="button" class="action action-clear <%= searchLabel ? '' : 'is-hidden' %>" aria-label="<%- gettext('Clear search') %>">
<i class="icon fa fa-times-circle" aria-hidden="true"></i><span class="sr"><%- gettext('Search') %></span>
</button>
</div>
<button type="submit" class="action action-search"><span class="icon fa-search" aria-hidden="true"></span><span class="sr"><%- gettext('Search') %></span></button>
</form>
</div>

View File

@@ -15,8 +15,8 @@
<% } %>
<div class="copy">
<h2 class="title title-3" id="<%= type %>-<%= intent %>-title"><%= title %></h2>
<% if(obj.message) { %><p class="message" id="<%= type %>-<%= intent %>-description"><%= message %></p><% } %>
<h2 class="title title-3" id="<%= type %>-<%= intent %>-title"><%- title %></h2>
<% if(obj.message) { %><p class="message" id="<%= type %>-<%= intent %>-description"><%- message %></p><% } %>
</div>
<% if(obj.actions) { %>
@@ -24,13 +24,13 @@
<ul>
<% if(actions.primary) { %>
<li class="nav-item">
<button class="action-primary <%= actions.primary.class %>"><%= actions.primary.text %></button>
<button class="action-primary <%= actions.primary.class %>"><%- actions.primary.text %></button>
</li>
<% } %>
<% if(actions.secondary) {
_.each(actions.secondary, function(secondary) { %>
<li class="nav-item">
<button class="action-secondary <%= secondary.class %>"><%= secondary.text %></button>
<button class="action-secondary <%= secondary.class %>"><%- secondary.text %></button>
</li>
<% });
} %>

View File

@@ -289,7 +289,7 @@ define(['js/capa/drag_and_drop/draggable_events', 'js/capa/drag_and_drop/draggab
draggableObj.iconEl.appendTo(draggableObj.containerEl);
draggableObj.iconWidth = draggableObj.iconEl.width();
draggableObj.iconWidth = draggableObj.iconEl.width() + 1;
draggableObj.iconHeight = draggableObj.iconEl.height();
draggableObj.iconWidthSmall = draggableObj.iconWidth;
draggableObj.iconHeightSmall = draggableObj.iconHeight;

View File

@@ -155,13 +155,14 @@
define([
// Run the common tests that use RequireJS.
'common-requirejs/include/common/js/spec/components/feedback_spec.js',
'common-requirejs/include/common/js/spec/components/list_spec.js',
'common-requirejs/include/common/js/spec/components/paginated_view_spec.js',
'common-requirejs/include/common/js/spec/components/paging_collection_spec.js',
'common-requirejs/include/common/js/spec/components/paging_header_spec.js',
'common-requirejs/include/common/js/spec/components/paging_footer_spec.js',
'common-requirejs/include/common/js/spec/components/view_utils_spec.js',
'common-requirejs/include/common/js/spec/components/feedback_spec.js'
'common-requirejs/include/common/js/spec/components/search_field_spec.js',
'common-requirejs/include/common/js/spec/components/view_utils_spec.js'
]);
}).call(this, requirejs, define);

View File

@@ -17,7 +17,8 @@ class AutoAuthPage(PageObject):
CONTENT_REGEX = r'.+? user (?P<username>\S+) \((?P<email>.+?)\) with password \S+ and user_id (?P<user_id>\d+)$'
def __init__(self, browser, username=None, email=None, password=None, staff=None, course_id=None, roles=None):
def __init__(self, browser, username=None, email=None, password=None, staff=None, course_id=None,
enrollment_mode=None, roles=None):
"""
Auto-auth is an end-point for HTTP GET requests.
By default, it will create accounts with random user credentials,
@@ -52,6 +53,8 @@ class AutoAuthPage(PageObject):
if course_id is not None:
self._params['course_id'] = course_id
if enrollment_mode:
self._params['enrollment_mode'] = enrollment_mode
if roles is not None:
self._params['roles'] = roles

View File

@@ -127,7 +127,7 @@ class CombinedLoginAndRegisterPage(PageObject):
@property
def url(self):
"""Return the URL for the combined login/registration page. """
url = "{base}/account/{login_or_register}".format(
url = "{base}/{login_or_register}".format(
base=BASE_URL,
login_or_register=self._start_page
)

View File

@@ -20,6 +20,25 @@ TEAMS_HEADER_CSS = '.teams-header'
CREATE_TEAM_LINK_CSS = '.create-team'
class TeamCardsMixin(object):
"""Provides common operations on the team card component."""
@property
def team_cards(self):
"""Get all the team cards on the page."""
return self.q(css='.team-card')
@property
def team_names(self):
"""Return the names of each team on the page."""
return self.q(css='h3.card-title').map(lambda e: e.text).results
@property
def team_descriptions(self):
"""Return the names of each team on the page."""
return self.q(css='p.card-description').map(lambda e: e.text).results
class TeamsPage(CoursePage):
"""
Teams page/tab.
@@ -84,7 +103,7 @@ class TeamsPage(CoursePage):
self.q(css='a.nav-item').filter(text=topic)[0].click()
class MyTeamsPage(CoursePage, PaginatedUIMixin):
class MyTeamsPage(CoursePage, PaginatedUIMixin, TeamCardsMixin):
"""
The 'My Teams' tab of the Teams page.
"""
@@ -98,11 +117,6 @@ class MyTeamsPage(CoursePage, PaginatedUIMixin):
return False
return 'is-active' in button_classes[0]
@property
def team_cards(self):
"""Get all the team cards on the page."""
return self.q(css='.team-card')
class BrowseTopicsPage(CoursePage, PaginatedUIMixin):
"""
@@ -128,6 +142,11 @@ class BrowseTopicsPage(CoursePage, PaginatedUIMixin):
"""Return a list of the topic names present on the page."""
return self.q(css=CARD_TITLE_CSS).map(lambda e: e.text).results
@property
def topic_descriptions(self):
"""Return a list of the topic descriptions present on the page."""
return self.q(css='p.card-description').map(lambda e: e.text).results
def browse_teams_for_topic(self, topic_name):
"""
Show the teams list for `topic_name`.
@@ -145,43 +164,43 @@ class BrowseTopicsPage(CoursePage, PaginatedUIMixin):
self.wait_for_ajax()
class BrowseTeamsPage(CoursePage, PaginatedUIMixin):
class BaseTeamsPage(CoursePage, PaginatedUIMixin, TeamCardsMixin):
"""
The paginated UI for browsing teams within a Topic on the Teams
page.
"""
def __init__(self, browser, course_id, topic):
"""
Set up `self.url_path` on instantiation, since it dynamically
reflects the current topic. Note that `topic` is a dict
representation of a topic following the same convention as a
course module's topic.
Note that `topic` is a dict representation of a topic following
the same convention as a course module's topic.
"""
super(BrowseTeamsPage, self).__init__(browser, course_id)
super(BaseTeamsPage, self).__init__(browser, course_id)
self.topic = topic
self.url_path = "teams/#topics/{topic_id}".format(topic_id=self.topic['id'])
def is_browser_on_page(self):
"""Check if we're on the teams list page for a particular topic."""
self.wait_for_element_presence('.team-actions', 'Wait for the bottom links to be present')
"""Check if we're on a teams list page for a particular topic."""
has_correct_url = self.url.endswith(self.url_path)
teams_list_view_present = self.q(css='.teams-main').present
return has_correct_url and teams_list_view_present
@property
def header_topic_name(self):
def header_name(self):
"""Get the topic name displayed by the page header"""
return self.q(css=TEAMS_HEADER_CSS + ' .page-title')[0].text
@property
def header_topic_description(self):
def header_description(self):
"""Get the topic description displayed by the page header"""
return self.q(css=TEAMS_HEADER_CSS + ' .page-description')[0].text
@property
def team_cards(self):
"""Get all the team cards on the page."""
return self.q(css='.team-card')
def sort_order(self):
"""Return the current sort order on the page."""
return self.q(
css='#paging-header-select option'
).filter(
lambda e: e.is_selected()
).results[0].text.strip()
def click_create_team_link(self):
""" Click on create team link."""
@@ -204,6 +223,55 @@ class BrowseTeamsPage(CoursePage, PaginatedUIMixin):
query.first.click()
self.wait_for_ajax()
def sort_teams_by(self, sort_order):
"""Sort the list of teams by the given `sort_order`."""
self.q(
css='#paging-header-select option[value={sort_order}]'.format(sort_order=sort_order)
).click()
self.wait_for_ajax()
@property
def _showing_search_results(self):
"""
Returns true if showing search results.
"""
return self.header_description.startswith(u"Showing results for")
def search(self, string):
"""
Searches for the specified string, and returns a SearchTeamsPage
representing the search results page.
"""
self.q(css='.search-field').first.fill(string)
self.q(css='.action-search').first.click()
self.wait_for(
lambda: self._showing_search_results,
description="Showing search results"
)
page = SearchTeamsPage(self.browser, self.course_id, self.topic)
page.wait_for_page()
return page
class BrowseTeamsPage(BaseTeamsPage):
"""
The paginated UI for browsing teams within a Topic on the Teams
page.
"""
def __init__(self, browser, course_id, topic):
super(BrowseTeamsPage, self).__init__(browser, course_id, topic)
self.url_path = "teams/#topics/{topic_id}".format(topic_id=self.topic['id'])
class SearchTeamsPage(BaseTeamsPage):
"""
The paginated UI for showing team search results.
page.
"""
def __init__(self, browser, course_id, topic):
super(SearchTeamsPage, self).__init__(browser, course_id, topic)
self.url_path = "teams/#topics/{topic_id}/search".format(topic_id=self.topic['id'])
class CreateOrEditTeamPage(CoursePage, FieldsMixin):
"""

View File

@@ -305,7 +305,7 @@ class ContainerPage(PageObject):
Returns:
list
"""
css = '#tab{tab_index} a[data-category={category_type}] span'.format(
css = '#tab{tab_index} button[data-category={category_type}] span'.format(
tab_index=tab_index,
category_type=category_type
)

View File

@@ -27,6 +27,12 @@ class CertificatesPage(CoursePage):
# Helpers
################
def refresh(self):
"""
Refresh the certificate page
"""
self.browser.refresh()
def is_browser_on_page(self):
"""
Verify that the browser is on the page and it is not still loading.
@@ -434,11 +440,8 @@ class Signatory(object):
"""
Save signatory.
"""
# Move focus from input to save button and then click it
self.certificate.page.browser.execute_script(
"$('{} .signatory-panel-save').focus()".format(self.get_selector())
)
self.find_css('.signatory-panel-save').first.click()
# Click on the save button.
self.certificate.page.q(css='button.signatory-panel-save').click()
self.mode = 'details'
self.certificate.page.wait_for_ajax()
self.wait_for_signatory_detail_view()
@@ -447,7 +450,7 @@ class Signatory(object):
"""
Cancel signatory editing.
"""
self.find_css('.signatory-panel-close').first.click()
self.certificate.page.q(css='button.signatory-panel-close').click()
self.mode = 'details'
self.wait_for_signatory_detail_view()

View File

@@ -33,9 +33,9 @@ class UsersPageMixin(PageObject):
def is_browser_on_page(self):
"""
Returns True iff the browser has loaded the page.
Returns True if the browser has loaded the page.
"""
return self.q(css='body.view-team').present
return self.q(css='body.view-team').present and not self.q(css='.ui-loading').present
@property
def users(self):

View File

@@ -72,7 +72,7 @@ def add_discussion(page, menu_index=0):
placement within the page).
"""
page.wait_for_component_menu()
click_css(page, 'a>span.large-discussion-icon', menu_index)
click_css(page, 'button>span.large-discussion-icon', menu_index)
def add_advanced_component(page, menu_index, name):
@@ -84,7 +84,7 @@ def add_advanced_component(page, menu_index, name):
"""
# Click on the Advanced icon.
page.wait_for_component_menu()
click_css(page, 'a>span.large-advanced-icon', menu_index, require_notification=False)
click_css(page, 'button>span.large-advanced-icon', menu_index, require_notification=False)
# This does an animation to hide the first level of buttons
# and instead show the Advanced buttons that are available.
@@ -95,7 +95,7 @@ def add_advanced_component(page, menu_index, name):
page.wait_for_element_visibility('.new-component-advanced', 'Advanced component menu is visible')
# Now click on the component to add it.
component_css = 'a[data-category={}]'.format(name)
component_css = 'button[data-category={}]'.format(name)
page.wait_for_element_visibility(component_css, 'Advanced component {} is visible'.format(name))
# Adding some components, e.g. the Discussion component, will make an ajax call
@@ -123,7 +123,7 @@ def add_component(page, item_type, specific_type):
'Wait for the add component menu to disappear'
)
all_options = page.q(css='.new-component-{} ul.new-component-template li a span'.format(item_type))
all_options = page.q(css='.new-component-{} ul.new-component-template li button span'.format(item_type))
chosen_option = all_options.filter(lambda el: el.text == specific_type).first
chosen_option.click()
wait_for_notification(page)
@@ -139,13 +139,13 @@ def add_html_component(page, menu_index, boilerplate=None):
"""
# Click on the HTML icon.
page.wait_for_component_menu()
click_css(page, 'a>span.large-html-icon', menu_index, require_notification=False)
click_css(page, 'button>span.large-html-icon', menu_index, require_notification=False)
# Make sure that the menu of HTML components is visible before clicking
page.wait_for_element_visibility('.new-component-html', 'HTML component menu is visible')
# Now click on the component to add it.
component_css = 'a[data-category=html]'
component_css = 'button[data-category=html]'
if boilerplate:
component_css += '[data-boilerplate={}]'.format(boilerplate)
else:

View File

@@ -30,7 +30,7 @@ CLASS_SELECTORS = {
}
BUTTON_SELECTORS = {
'create_video': 'a[data-category="video"]',
'create_video': 'button[data-category="video"]',
'handout_download': '.video-handout.video-download-button a',
'handout_download_editor': '.wrapper-comp-setting.file-uploader .download-action',
'upload_asset': '.upload-action',

View File

@@ -109,7 +109,7 @@ class LoginFromCombinedPageTest(UniqueCourseTest):
self.login_page.visit().toggle_form()
self.assertEqual(self.login_page.current_form, "register")
@flaky # TODO fix this, see ECOM-1165
@flaky # ECOM-1165
def test_password_reset_success(self):
# Create a user account
email, password = self._create_unique_user() # pylint: disable=unused-variable

View File

@@ -168,32 +168,12 @@ class ProctoredExamsTest(BaseInstructorDashboardTest):
# Auto-auth register for the course.
self._auto_auth(self.USERNAME, self.EMAIL, False)
def _auto_auth(self, username, email, staff):
def _auto_auth(self, username, email, staff, enrollment_mode="honor"):
"""
Logout and login with given credentials.
"""
AutoAuthPage(self.browser, username=username, email=email,
course_id=self.course_id, staff=staff).visit()
def _login_as_a_verified_user(self):
"""
login as a verififed user
"""
self._auto_auth(self.USERNAME, self.EMAIL, False)
# the track selection page cannot be visited. see the other tests to see if any prereq is there.
# Navigate to the track selection page
self.track_selection_page.visit()
# Enter the payment and verification flow by choosing to enroll as verified
self.track_selection_page.enroll('verified')
# Proceed to the fake payment page
self.payment_and_verification_flow.proceed_to_payment()
# Submit payment
self.fake_payment_page.submit_payment()
course_id=self.course_id, staff=staff, enrollment_mode=enrollment_mode).visit()
def _create_a_proctored_exam_and_attempt(self):
"""
@@ -212,7 +192,7 @@ class ProctoredExamsTest(BaseInstructorDashboardTest):
# login as a verified student and visit the courseware.
LogoutPage(self.browser).visit()
self._login_as_a_verified_user()
self._auto_auth(self.USERNAME, self.EMAIL, False, enrollment_mode="verified")
self.courseware_page.visit()
# Start the proctored exam.
@@ -235,7 +215,7 @@ class ProctoredExamsTest(BaseInstructorDashboardTest):
# login as a verified student and visit the courseware.
LogoutPage(self.browser).visit()
self._login_as_a_verified_user()
self._auto_auth(self.USERNAME, self.EMAIL, False, enrollment_mode="verified")
self.courseware_page.visit()
# Start the proctored exam.

View File

@@ -5,6 +5,7 @@ Bok choy acceptance tests for problems in the LMS
See also old lettuce tests in lms/djangoapps/courseware/features/problems.feature
"""
from textwrap import dedent
from flaky import flaky
from ..helpers import UniqueCourseTest
from ...pages.studio.auto_auth import AutoAuthPage
@@ -191,6 +192,7 @@ class ProblemHintWithHtmlTest(ProblemsTest, EventsTestMixin):
""")
return XBlockFixtureDesc('problem', 'PROBLEM HTML HINT TEST', data=xml)
@flaky # TODO fix this, see TNL-3183
def test_check_hint(self):
"""
Test clicking Check shows the extended hint in the problem message.

View File

@@ -3,13 +3,16 @@ Acceptance tests for the teams feature.
"""
import json
import random
import time
from dateutil.parser import parse
import ddt
from flaky import flaky
from nose.plugins.attrib import attr
from uuid import uuid4
from unittest import skip
from ..helpers import UniqueCourseTest
from ..helpers import UniqueCourseTest, EventsTestMixin
from ...fixtures import LMS_BASE_URL
from ...fixtures.course import CourseFixture
from ...fixtures.discussion import (
@@ -26,7 +29,7 @@ from ...pages.lms.teams import TeamsPage, MyTeamsPage, BrowseTopicsPage, BrowseT
TOPICS_PER_PAGE = 12
class TeamsTabBase(UniqueCourseTest):
class TeamsTabBase(EventsTestMixin, UniqueCourseTest):
"""Base class for Teams Tab tests"""
def setUp(self):
super(TeamsTabBase, self).setUp()
@@ -38,7 +41,7 @@ class TeamsTabBase(UniqueCourseTest):
"""Create `num_topics` test topics."""
return [{u"description": i, u"name": i, u"id": i} for i in map(str, xrange(num_topics))]
def create_teams(self, topic, num_teams):
def create_teams(self, topic, num_teams, time_between_creation=0):
"""Create `num_teams` teams belonging to `topic`."""
teams = []
for i in xrange(num_teams):
@@ -55,6 +58,10 @@ class TeamsTabBase(UniqueCourseTest):
data=json.dumps(team),
headers=self.course_fixture.headers
)
# Sadly, this sleep is necessary in order to ensure that
# sorting by last_activity_at works correctly when running
# in Jenkins.
time.sleep(time_between_creation)
teams.append(json.loads(response.text))
return teams
@@ -107,15 +114,8 @@ class TeamsTabBase(UniqueCourseTest):
self.assertEqual(expected_team['name'], team_card_name)
self.assertEqual(expected_team['description'], team_card_description)
team_cards = page.team_cards
team_card_names = [
team_card.find_element_by_css_selector('.card-title').text
for team_card in team_cards.results
]
team_card_descriptions = [
team_card.find_element_by_css_selector('.card-description').text
for team_card in team_cards.results
]
team_card_names = page.team_names
team_card_descriptions = page.team_descriptions
map(assert_team_equal, expected_teams, team_card_names, team_card_descriptions)
def verify_my_team_count(self, expected_number_of_teams):
@@ -124,6 +124,10 @@ class TeamsTabBase(UniqueCourseTest):
# We are doing these operations on this top-level page object to avoid reloading the page.
self.teams_page.verify_my_team_count(expected_number_of_teams)
def only_team_events(self, event):
"""Filter out all non-team events."""
return event['event_type'].startswith('edx.team.')
@ddt.ddt
@attr('shard_5')
@@ -445,7 +449,7 @@ class BrowseTopicsTest(TeamsTabBase):
{u"max_team_size": 1, u"topics": [{"name": "", "id": "", "description": initial_description}]}
)
self.topics_page.visit()
truncated_description = self.topics_page.topic_cards[0].text
truncated_description = self.topics_page.topic_descriptions[0]
self.assertLess(len(truncated_description), len(initial_description))
self.assertTrue(truncated_description.endswith('...'))
self.assertIn(truncated_description.split('...')[0], initial_description)
@@ -468,11 +472,12 @@ class BrowseTopicsTest(TeamsTabBase):
self.topics_page.browse_teams_for_topic('Example Topic')
browse_teams_page = BrowseTeamsPage(self.browser, self.course_id, topic)
self.assertTrue(browse_teams_page.is_browser_on_page())
self.assertEqual(browse_teams_page.header_topic_name, 'Example Topic')
self.assertEqual(browse_teams_page.header_topic_description, 'Description')
self.assertEqual(browse_teams_page.header_name, 'Example Topic')
self.assertEqual(browse_teams_page.header_description, 'Description')
@attr('shard_5')
@ddt.ddt
class BrowseTeamsWithinTopicTest(TeamsTabBase):
"""
Tests for browsing Teams within a Topic on the Teams page.
@@ -482,21 +487,45 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
def setUp(self):
super(BrowseTeamsWithinTopicTest, self).setUp()
self.topic = {u"name": u"Example Topic", u"id": "example_topic", u"description": "Description"}
self.set_team_configuration({'course_id': self.course_id, 'max_team_size': 10, 'topics': [self.topic]})
self.max_team_size = 10
self.set_team_configuration({
'course_id': self.course_id,
'max_team_size': self.max_team_size,
'topics': [self.topic]
})
self.browse_teams_page = BrowseTeamsPage(self.browser, self.course_id, self.topic)
self.topics_page = BrowseTopicsPage(self.browser, self.course_id)
def teams_with_default_sort_order(self, teams):
"""Return a list of teams sorted according to the default ordering
(last_activity_at, with a secondary sort by open slots).
"""
return sorted(
sorted(teams, key=lambda t: len(t['membership']), reverse=True),
key=lambda t: parse(t['last_activity_at']).replace(microsecond=0),
reverse=True
)
def verify_page_header(self):
"""Verify that the page header correctly reflects the current topic's name and description."""
self.assertEqual(self.browse_teams_page.header_topic_name, self.topic['name'])
self.assertEqual(self.browse_teams_page.header_topic_description, self.topic['description'])
self.assertEqual(self.browse_teams_page.header_name, self.topic['name'])
self.assertEqual(self.browse_teams_page.header_description, self.topic['description'])
def verify_on_page(self, page_num, total_teams, pagination_header_text, footer_visible):
def verify_search_header(self, search_results_page, search_query):
"""Verify that the page header correctly reflects the current topic's name and description."""
self.assertEqual(search_results_page.header_name, 'Team Search')
self.assertEqual(
search_results_page.header_description,
'Showing results for "{search_query}"'.format(search_query=search_query)
)
def verify_on_page(self, teams_page, page_num, total_teams, pagination_header_text, footer_visible):
"""
Verify that we are on the correct team list page.
Arguments:
page_num (int): The one-indexed page we expect to be on
teams_page (BaseTeamsPage): The teams page object that should be the current page.
page_num (int): The one-indexed page number that we expect to be on
total_teams (list): An unsorted list of all the teams for the
current topic
pagination_header_text (str): Text we expect to see in the
@@ -504,18 +533,75 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
footer_visible (bool): Whether we expect to see the pagination
footer controls.
"""
alphabetized_teams = sorted(total_teams, key=lambda team: team['name'])
self.assertEqual(self.browse_teams_page.get_pagination_header_text(), pagination_header_text)
sorted_teams = self.teams_with_default_sort_order(total_teams)
self.assertTrue(teams_page.get_pagination_header_text().startswith(pagination_header_text))
self.verify_teams(
self.browse_teams_page,
alphabetized_teams[(page_num - 1) * self.TEAMS_PAGE_SIZE:page_num * self.TEAMS_PAGE_SIZE]
teams_page,
sorted_teams[(page_num - 1) * self.TEAMS_PAGE_SIZE:page_num * self.TEAMS_PAGE_SIZE]
)
self.assertEqual(
self.browse_teams_page.pagination_controls_visible(),
teams_page.pagination_controls_visible(),
footer_visible,
msg='Expected paging footer to be ' + 'visible' if footer_visible else 'invisible'
)
@ddt.data(
('open_slots', 'last_activity_at', True),
('last_activity_at', 'open_slots', True)
)
@ddt.unpack
def test_sort_teams(self, sort_order, secondary_sort_order, reverse):
"""
Scenario: the user should be able to sort the list of teams by open slots or last activity
Given I am enrolled in a course with team configuration and topics
When I visit the Teams page
And I browse teams within a topic
Then I should see a list of teams for that topic
When I choose a sort order
Then I should see the paginated list of teams in that order
"""
teams = self.create_teams(self.topic, self.TEAMS_PAGE_SIZE + 1)
for i, team in enumerate(random.sample(teams, len(teams))):
for _ in range(i):
user_info = AutoAuthPage(self.browser, course_id=self.course_id).visit().user_info
self.create_membership(user_info['username'], team['id'])
team['open_slots'] = self.max_team_size - i
# Parse last activity date, removing microseconds because
# the Django ORM does not support them. Will be fixed in
# Django 1.8.
team['last_activity_at'] = parse(team['last_activity_at']).replace(microsecond=0)
# Re-authenticate as staff after creating users
AutoAuthPage(
self.browser,
course_id=self.course_id,
staff=True
).visit()
self.browse_teams_page.visit()
self.browse_teams_page.sort_teams_by(sort_order)
team_names = self.browse_teams_page.team_names
self.assertEqual(len(team_names), self.TEAMS_PAGE_SIZE)
sorted_teams = [
team['name']
for team in sorted(
sorted(teams, key=lambda t: t[secondary_sort_order], reverse=reverse),
key=lambda t: t[sort_order],
reverse=reverse
)
][:self.TEAMS_PAGE_SIZE]
self.assertEqual(team_names, sorted_teams)
def test_default_sort_order(self):
"""
Scenario: the list of teams should be sorted by last activity by default
Given I am enrolled in a course with team configuration and topics
When I visit the Teams page
And I browse teams within a topic
Then I should see a list of teams for that topic, sorted by last activity
"""
self.create_teams(self.topic, self.TEAMS_PAGE_SIZE + 1)
self.browse_teams_page.visit()
self.assertEqual(self.browse_teams_page.sort_order, 'last activity')
def test_no_teams(self):
"""
Scenario: Visiting a topic with no teams should not display any teams.
@@ -529,7 +615,7 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
"""
self.browse_teams_page.visit()
self.verify_page_header()
self.assertEqual(self.browse_teams_page.get_pagination_header_text(), 'Showing 0 out of 0 total')
self.assertTrue(self.browse_teams_page.get_pagination_header_text().startswith('Showing 0 out of 0 total'))
self.assertEqual(len(self.browse_teams_page.team_cards), 0, msg='Expected to see no team cards')
self.assertFalse(
self.browse_teams_page.pagination_controls_visible(),
@@ -548,10 +634,12 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
And I should see a button to add a team
And I should not see a pagination footer
"""
teams = self.create_teams(self.topic, self.TEAMS_PAGE_SIZE)
teams = self.teams_with_default_sort_order(
self.create_teams(self.topic, self.TEAMS_PAGE_SIZE, time_between_creation=1)
)
self.browse_teams_page.visit()
self.verify_page_header()
self.assertEqual(self.browse_teams_page.get_pagination_header_text(), 'Showing 1-10 out of 10 total')
self.assertTrue(self.browse_teams_page.get_pagination_header_text().startswith('Showing 1-10 out of 10 total'))
self.verify_teams(self.browse_teams_page, teams)
self.assertFalse(
self.browse_teams_page.pagination_controls_visible(),
@@ -571,14 +659,14 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
And when I click on the previous page button
Then I should see that I am on the first page of results
"""
teams = self.create_teams(self.topic, self.TEAMS_PAGE_SIZE + 1)
teams = self.create_teams(self.topic, self.TEAMS_PAGE_SIZE + 1, time_between_creation=1)
self.browse_teams_page.visit()
self.verify_page_header()
self.verify_on_page(1, teams, 'Showing 1-10 out of 11 total', True)
self.verify_on_page(self.browse_teams_page, 1, teams, 'Showing 1-10 out of 11 total', True)
self.browse_teams_page.press_next_page_button()
self.verify_on_page(2, teams, 'Showing 11-11 out of 11 total', True)
self.verify_on_page(self.browse_teams_page, 2, teams, 'Showing 11-11 out of 11 total', True)
self.browse_teams_page.press_previous_page_button()
self.verify_on_page(1, teams, 'Showing 1-10 out of 11 total', True)
self.verify_on_page(self.browse_teams_page, 1, teams, 'Showing 1-10 out of 11 total', True)
def test_teams_page_input(self):
"""
@@ -593,28 +681,24 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
When I input the first page
Then I should see that I am on the first page of results
"""
teams = self.create_teams(self.topic, self.TEAMS_PAGE_SIZE + 10)
teams = self.create_teams(self.topic, self.TEAMS_PAGE_SIZE + 10, time_between_creation=1)
self.browse_teams_page.visit()
self.verify_page_header()
self.verify_on_page(1, teams, 'Showing 1-10 out of 20 total', True)
self.verify_on_page(self.browse_teams_page, 1, teams, 'Showing 1-10 out of 20 total', True)
self.browse_teams_page.go_to_page(2)
self.verify_on_page(2, teams, 'Showing 11-20 out of 20 total', True)
self.verify_on_page(self.browse_teams_page, 2, teams, 'Showing 11-20 out of 20 total', True)
self.browse_teams_page.go_to_page(1)
self.verify_on_page(1, teams, 'Showing 1-10 out of 20 total', True)
self.verify_on_page(self.browse_teams_page, 1, teams, 'Showing 1-10 out of 20 total', True)
def test_navigation_links(self):
def test_browse_team_topics(self):
"""
Scenario: User should be able to navigate to "browse all teams" and "search team description" links.
Given I am enrolled in a course with a team configuration and a topic
containing one team
When I visit the Teams page for that topic
Given I am enrolled in a course with teams enabled
When I visit the Teams page for a topic
Then I should see the correct page header
And I should see the link to "browse all team"
And I should navigate to that link
And I see the relevant page loaded
And I should see the link to "search teams"
And I should navigate to that link
And I see the relevant page loaded
And I should see the link to "browse teams in other topics"
When I should navigate to that link
Then I should see the topic browse page
"""
self.browse_teams_page.visit()
self.verify_page_header()
@@ -622,10 +706,24 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
self.browse_teams_page.click_browse_all_teams_link()
self.assertTrue(self.topics_page.is_browser_on_page())
@skip('Disabled until search connectivity issues are resolved, see TNL-3206')
def test_search(self):
"""
Scenario: User should be able to search for a team
Given I am enrolled in a course with teams enabled
When I visit the Teams page for that topic
And I search for 'banana'
Then I should see the search result page
And the search header should be shown
And 0 results should be shown
"""
# Note: all searches will return 0 results with the mock search server
# used by Bok Choy.
self.create_teams(self.topic, 5)
self.browse_teams_page.visit()
self.verify_page_header()
self.browse_teams_page.click_search_team_link()
# TODO Add search page expectation once that implemented.
search_results_page = self.browse_teams_page.search('banana')
self.verify_search_header(search_results_page, 'banana')
self.assertTrue(search_results_page.get_pagination_header_text().startswith('Showing 0 out of 0 total'))
@attr('shard_5')
@@ -652,8 +750,8 @@ class TeamFormActions(TeamsTabBase):
self.browse_teams_page.click_create_team_link()
self.verify_page_header(
title='Create a New Team',
description='Create a new team if you can\'t find existing teams to '
'join, or if you would like to learn with friends you know.',
description='Create a new team if you can\'t find an existing team to join, '
'or if you would like to learn with friends you know.',
breadcrumbs='All Topics {topic_name}'.format(topic_name=self.topic['name'])
)
@@ -807,7 +905,8 @@ class CreateTeamTest(TeamFormActions):
Then I should see the Create Team header and form
When I fill all the fields present with appropriate data
And I click Create button
Then I should see the page for my team
Then I expect analytics events to be emitted
And I should see the page for my team
And I should see the message that says "You are member of this team"
And the new team should be added to the list of teams within the topic
And the number of teams should be updated on the topic card
@@ -819,7 +918,24 @@ class CreateTeamTest(TeamFormActions):
self.verify_and_navigate_to_create_team_page()
self.fill_create_or_edit_form()
self.create_or_edit_team_page.submit_form()
expected_events = [
{
'event_type': 'edx.team.created',
'event': {
'course_id': self.course_id,
}
},
{
'event_type': 'edx.team.learner_added',
'event': {
'course_id': self.course_id,
'add_method': 'added_on_create',
}
}
]
with self.assert_events_match_during(event_filter=self.only_team_events, expected_events=expected_events):
self.create_or_edit_team_page.submit_form()
# Verify that the page is shown for the new team
team_page = TeamPage(self.browser, self.course_id)
@@ -848,13 +964,13 @@ class CreateTeamTest(TeamFormActions):
Then I should see teams list page without any new team.
And if I switch to "My Team", it shows no teams
"""
self.assertEqual(self.browse_teams_page.get_pagination_header_text(), 'Showing 0 out of 0 total')
self.assertTrue(self.browse_teams_page.get_pagination_header_text().startswith('Showing 0 out of 0 total'))
self.verify_and_navigate_to_create_team_page()
self.create_or_edit_team_page.cancel_team()
self.assertTrue(self.browse_teams_page.is_browser_on_page())
self.assertEqual(self.browse_teams_page.get_pagination_header_text(), 'Showing 0 out of 0 total')
self.assertTrue(self.browse_teams_page.get_pagination_header_text().startswith('Showing 0 out of 0 total'))
self.teams_page.click_all_topics()
self.teams_page.verify_team_count_in_first_topic(0)
@@ -1238,6 +1354,7 @@ class TeamPageTest(TeamsTabBase):
And I should not see New Post button
When I click on Join Team button
Then there should be no Join Team button and no message
And an analytics event should be emitted
And I should see the updated information under Team Details
And I should see New Post button
And if I switch to "My Team", the team I have joined is displayed
@@ -1245,7 +1362,17 @@ class TeamPageTest(TeamsTabBase):
self._set_team_configuration_and_membership(create_membership=False)
self.team_page.visit()
self.assertTrue(self.team_page.join_team_button_present)
self.team_page.click_join_team_button()
expected_events = [
{
'event_type': 'edx.team.learner_added',
'event': {
'course_id': self.course_id,
'add_method': 'joined_from_team_view'
}
}
]
with self.assert_events_match_during(event_filter=self.only_team_events, expected_events=expected_events):
self.team_page.click_join_team_button()
self.assertFalse(self.team_page.join_team_button_present)
self.assertFalse(self.team_page.join_team_message_present)
self.assert_team_details(num_members=1, is_member=True)
@@ -1305,6 +1432,7 @@ class TeamPageTest(TeamsTabBase):
Then I should see Leave Team link
When I click on Leave Team link
Then user should be removed from team
And an analytics event should be emitted
And I should see Join Team button
And I should not see New Post button
And if I switch to "My Team", the team I have left is not displayed
@@ -1313,7 +1441,17 @@ class TeamPageTest(TeamsTabBase):
self.team_page.visit()
self.assertFalse(self.team_page.join_team_button_present)
self.assert_team_details(num_members=1)
self.team_page.click_leave_team_link()
expected_events = [
{
'event_type': 'edx.team.learner_removed',
'event': {
'course_id': self.course_id,
'remove_method': 'self_removal'
}
}
]
with self.assert_events_match_during(event_filter=self.only_team_events, expected_events=expected_events):
self.team_page.click_leave_team_link()
self.assert_team_details(num_members=0, is_member=False)
self.assertTrue(self.team_page.join_team_button_present)

View File

@@ -2,6 +2,8 @@
Acceptance tests for Studio related to the asset index page.
"""
from flaky import flaky
from ...pages.studio.asset_index import AssetIndexPage
from .base_studio_test import StudioCourseTest
@@ -35,6 +37,7 @@ class AssetIndexTest(StudioCourseTest):
"""
self.asset_page.visit()
@flaky # TODO fix this, see SOL-1160
def test_type_filter_exists(self):
"""
Make sure type filter is on the page.

View File

@@ -522,9 +522,7 @@ class LibraryUsersPageTest(StudioLibraryTest):
"""
self.page = LibraryUsersPage(self.browser, self.library_key)
self.page.visit()
self.page.wait_until_no_loading_indicator()
@flaky # TODO fix this; see TNL-2647
def test_user_management(self):
"""
Scenario: Ensure that we can edit the permissions of users.

View File

@@ -170,6 +170,8 @@ class CertificatesTest(StudioCourseTest):
self.assertEqual(len(self.certificates_page.certificates), 1)
#Refreshing the page, So page have the updated certificate object.
self.certificates_page.refresh()
signatory = self.certificates_page.certificates[0].signatories[0]
self.assertIn("Updated signatory name", signatory.name)
self.assertIn("Update signatory title", signatory.title)

View File

@@ -3,6 +3,7 @@
import datetime
import json
import ddt
import unittest
from ..helpers import EventsTestMixin
from .test_video_module import VideoBaseTest
@@ -60,6 +61,7 @@ class VideoEventsTestMixin(EventsTestMixin, VideoBaseTest):
class VideoEventsTest(VideoEventsTestMixin):
""" Test video player event emission """
@unittest.skip('AN-5867')
def test_video_control_events(self):
"""
Scenario: Video component is rendered in the LMS in Youtube mode without HTML5 sources

Binary file not shown.

View File

@@ -129,7 +129,7 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-21 14:18+0000\n"
"POT-Creation-Date: 2015-09-04 14:07+0000\n"
"PO-Revision-Date: 2015-08-12 08:13+0000\n"
"Last-Translator: Ahmed Jazzar <ajazzar@edraak.org>\n"
"Language-Team: Arabic (http://www.transifex.com/open-edx/edx-platform/language/ar/)\n"
@@ -1381,10 +1381,6 @@ msgstr "صحيح"
msgid "incorrect"
msgstr "غير صحيح"
#: common/lib/capa/capa/inputtypes.py
msgid "partially correct"
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "incomplete"
msgstr "ناقص"
@@ -1407,10 +1403,6 @@ msgstr "هذا صحيح"
msgid "This is incorrect."
msgstr "هذا خطأ"
#: common/lib/capa/capa/inputtypes.py
msgid "This is partially correct."
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "This is unanswered."
msgstr "هذا غير مجاب عليه"
@@ -5190,8 +5182,15 @@ msgid "{month} {day}, {year}"
msgstr "{month} {day}، {year}"
#: lms/djangoapps/certificates/views/webview.py
msgid "a course of study offered by {partner_name}, through {platform_name}."
msgstr "مساق دروس يقدِّمه {partner_name}، عبر {platform_name}."
msgid ""
"a course of study offered by {partner_short_name}, an online learning "
"initiative of {partner_long_name} through {platform_name}."
msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"a course of study offered by {partner_short_name}, through {platform_name}."
msgstr ""
#. Translators: Accomplishments describe the awards/certifications obtained by
#. students on this platform
@@ -5302,16 +5301,14 @@ msgstr "تُقِرّ {platform_name} بإنجازات الطالب التالي
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"This is a valid {platform_name} certificate for {user_name}, who "
"participated in {partner_name} {course_number}"
"participated in {partner_short_name} {course_number}"
msgstr ""
"هذه شهادة صالحة من {platform_name} للمستخدم {user_name} الذي شارك في "
"{partner_name} {course_number}"
#. Translators: This text is bound to the HTML 'title' element of the page
#. and appears in the browser title bar
#: lms/djangoapps/certificates/views/webview.py
msgid "{partner_name} {course_number} Certificate | {platform_name}"
msgstr "شهادة {partner_name} {course_number} | {platform_name}"
msgid "{partner_short_name} {course_number} Certificate | {platform_name}"
msgstr ""
#. Translators: This text fragment appears after the student's name
#. (displayed in a large font) on the certificate
@@ -5478,6 +5475,14 @@ msgstr ""
"إذا لم يظهر مساقك على لوحة معلوماتك، يُرجى الاتصال بـ "
"{payment_support_link}."
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "{course_id} is not a valid course key."
msgstr ""
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "Course {course_id} does not exist."
msgstr ""
#: lms/djangoapps/course_wiki/tab.py lms/djangoapps/course_wiki/views.py
#: lms/templates/wiki/base.html
msgid "Wiki"
@@ -6032,6 +6037,23 @@ msgstr "اسم المستخدم {user} موجود مسبقًا."
msgid "File is not attached."
msgstr "الملف غير مُرفَق. "
#: lms/djangoapps/instructor/views/api.py
msgid "Could not find problem with this location."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"The problem responses report is being created. To view the status of the "
"report, see Pending Tasks below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A problem responses report generation task is already in progress. Check the"
" 'Pending Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid "Invoice number '{num}' does not exist."
msgstr " الفاتورة رقم '{num}' غير موجودة."
@@ -6451,6 +6473,10 @@ msgstr "لا توجد وضعية للمساق CourseMode باسم ({mode_slug})
msgid "CourseMode price updated successfully"
msgstr "تمّ عملية تحديث سعر CourseMode بنجاح"
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "No end date set"
msgstr ""
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "Enrollment data is now available in {dashboard_link}."
msgstr "تتوافر بيانات التسجيل الآن على {dashboard_link}."
@@ -6557,18 +6583,6 @@ msgstr "بريد إلكتروني خارجي"
msgid "Grades for assignment \"{name}\""
msgstr "درجات الواجب \"{name}\""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Found {num} records to dump."
msgstr "وُجدت {num} سجلّات للتخلّص منها."
#: lms/djangoapps/instructor/views/legacy.py
msgid "Couldn't find module with that urlname."
msgstr "نأسف لتعذّر إيجاد وحدة بذلك الرابط."
#: lms/djangoapps/instructor/views/legacy.py
msgid "Student state for problem {problem}"
msgstr "حالة الطالب بالنسبة للمسألة {problem}"
#: lms/djangoapps/instructor/views/legacy.py
msgid "Grades from {course_id}"
msgstr "الدرجات من المساق رقم {course_id}"
@@ -6736,6 +6750,12 @@ msgstr "جرى الحذف"
msgid "emailed"
msgstr "الإرسال بالبريد الإلكتروني"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr "الاستحداث"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -6748,12 +6768,6 @@ msgstr "التقييم "
msgid "problem distribution graded"
msgstr "تقييم توزيع المسائل "
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr "الاستحداث"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -8382,12 +8396,12 @@ msgid "course_id must be provided"
msgstr "يجب توفير الرقم التغريفي للمساق course_id."
#: lms/djangoapps/teams/views.py
msgid "The supplied topic id {topic_id} is not valid"
msgstr "الرقم التعريفي الذي جرى توفيره حول الموضوع {topic_id} غير صالح."
msgid "text_search and order_by cannot be provided together"
msgstr ""
#: lms/djangoapps/teams/views.py
msgid "text_search is not yet supported."
msgstr "إنّ خاصّية البحث في النصّ text_search غير مدعومة بعد."
msgid "The supplied topic id {topic_id} is not valid"
msgstr "الرقم التعريفي الذي جرى توفيره حول الموضوع {topic_id} غير صالح."
#. Translators: 'ordering' is a string describing a way
#. of ordering a list. For example, {ordering} may be
@@ -10195,6 +10209,10 @@ msgstr "المساعدة"
msgid "Sign Out"
msgstr "تسجيل الخروج"
#: common/lib/capa/capa/templates/codeinput.html
msgid "{programming_language} editor"
msgstr ""
#: common/templates/license.html
msgid "All Rights Reserved"
msgstr "جميع الحقوق محفوظة"
@@ -12862,8 +12880,10 @@ msgid "Section:"
msgstr "القسم:"
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid "Problem urlname:"
msgstr "اسم الرابط urlname الخاص بالمسألة: "
msgid ""
"To download a CSV listing student responses to a given problem, visit the "
"Data Download section of the Instructor Dashboard."
msgstr ""
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid ""
@@ -14860,6 +14880,20 @@ msgstr ""
msgid "Generate Proctored Exam Results Report"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"To generate a CSV file that lists all student answers to a given problem, "
"enter the location of the problem (from its Staff Debug Info)."
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Problem location: "
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Download a CSV of problem responses"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"For smaller courses, click to list profile information for enrolled students"
@@ -17396,60 +17430,51 @@ msgid "This module is not enabled."
msgstr "هذه الوحدة غير مفعَّلة."
#: cms/templates/certificates.html
msgid ""
"Upon successful completion of your course, learners receive a certificate to"
" acknowledge their accomplishment. If you are a course team member with the "
"Admin role in Studio, you can configure your course certificate."
msgid "Working with Certificates"
msgstr ""
"عند استكمال الطلّاب لمساقك بنجاح، يحصلون على شهادة تُثبِت إنجازهم. وإذا كنت "
"عضوًا في فريق المساق بدور مشرِف في الاستوديو، يمكنك إعداد شهادة مساقك."
#: cms/templates/certificates.html
msgid ""
"Click {em_start}Add your first certificate{em_end} to add a certificate "
"configuration. Upload the organization logo to be used on the certificate, "
"and specify at least one signatory. You can include up to four signatories "
"for a certificate. You can also upload a signature image file for each "
"signatory. {em_start}Note:{em_end} Signature images are used only for "
"verified certificates. Optionally, specify a different course title to use "
"on your course certificate. You might want to use a different title if, for "
"example, the official course name is too long to display well on a "
"certificate."
"Specify a course title to use on the certificate if the course's official "
"title is too long to be displayed well."
msgstr ""
"يُرجى النقر على {em_start}أَضِف شهادتك الأولى{em_end} لتُضيف إعدادات "
"الشهادة. ثمّ حَمِّل شعار المؤسّسة لوضعه على الشهادة وحدِّد موقِّعًا واحدًا "
"على الأقلّ وأربعة على الأكثر لكل شهادة. ويمكنك أيضًا تحميل صورة التوقيع لكل "
"موقّع. {em_start}ملاحظة:{em_end} تُستخدَم صور التواقيع فقط للشهادات "
"الموثَّقة. أو إذا أردت، يمكنك أن تحدِّد اسمًا مختلفًا للمساق لوضعه على "
"شهادتك. وقد ترغب في استخدام اسم مختلف إذا كان، مثلًا، الاسم الرسمي للمساق "
"طويلًا جدًّا إلى درجة أنّه لن يبدو واضحًا على الشهادة."
#: cms/templates/certificates.html
msgid ""
"Select a course mode and click {em_start}Preview Certificate{em_end} to "
"preview the certificate that a learner in the selected enrollment track "
"would receive. When the certificate is ready for issuing, click "
"{em_start}Activate.{em_end} To stop issuing an active certificate, click "
"{em_start}Deactivate{em_end}."
"For verified certificates, specify between one and four signatories and "
"upload the associated images."
msgstr ""
"يُرجى اختيار وضعية للمساق ثمّ النقر على {em_start}معاينة الشهادة{em_end} "
"لمعاينة الشهادة التي سيحصل عليها المتعلّم في مسار التسجيل المُنتقى. وعندما "
"تَجهَز الشهادة للإصدار، يُرجى النقر على {em_start}تفعيل.{em_end}. ولإيقاف "
"إصدار شهادة مفعَّلة، يُرجى النقر على {em_start}إبطال التفعيل{em_end}."
#: cms/templates/certificates.html
msgid ""
" To edit the certificate configuration, hover over the top right corner of "
"the form and click {em_start}Edit{em_end}. To delete a certificate, hover "
"over the top right corner of the form and click the delete icon. In general,"
" do not delete certificates after a course has started, because some "
"certificates might already have been issued to learners."
"To edit or delete a certificate before it is activated, hover over the top "
"right corner of the form and select {em_start}Edit{em_end} or the delete "
"icon."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"To view a sample certificate, choose a course mode and select "
"{em_start}Preview Certificate{em_end}."
msgstr ""
#: cms/templates/certificates.html
msgid "Issuing Certificates to Learners"
msgstr ""
#: cms/templates/certificates.html
msgid ""
"To begin issuing certificates, a course team member with the Admin role "
"selects {em_start}Activate{em_end}. Course team members without the Admin "
"role cannot edit or delete an activated certificate."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"{em_start}Do not{em_end} delete certificates after a course has started; "
"learners who have already earned certificates will no longer be able to "
"access them."
msgstr ""
"لتعديل إعدادات الشهادة، يُرجى تحريك الماوس إلى الزاوية العليا اليمنى من "
"الاستمارة والنقر على {em_start}تعديل{em_end}. ولحذف إحدى الشهادات، يُرجى "
"تحريك الماوس إلى الزاوية العليا اليمنى من الاستمارة والنقر على رمز الحذف. "
"وبشكل عام، لا تحذف الشهادات بعد بدء المساق، لأنّ بعض الشهادات قد تكون "
"أُصدِرت مسبقًا للمتعلِّمين."
#: cms/templates/certificates.html
msgid "Learn more about certificates"

View File

@@ -57,6 +57,7 @@
# Translators:
# Abdelghani Gadiri <wh.gnu.linux@gmail.com>, 2014
# qrfahasan <ahasan@qrf.org>, 2014
# Ahmad <reload_cobra2@yahoo.com>, 2015
# Ahmed Jazzar <ajazzar@edraak.org>, 2015
# mohammad hamdi <babrica@hotmail.com>, 2014
# may <may@qordoba.com>, 2014
@@ -80,8 +81,8 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-21 14:17+0000\n"
"PO-Revision-Date: 2015-08-21 02:41+0000\n"
"POT-Creation-Date: 2015-09-04 14:06+0000\n"
"PO-Revision-Date: 2015-09-04 14:08+0000\n"
"Last-Translator: Sarina Canelake <sarina@edx.org>\n"
"Language-Team: Arabic (http://www.transifex.com/open-edx/edx-platform/language/ar/)\n"
"MIME-Version: 1.0\n"
@@ -127,8 +128,8 @@ msgstr "موافق"
#: cms/static/js/views/show_textbook.js cms/static/js/views/validation.js
#: cms/static/js/views/modals/base_modal.js
#: cms/static/js/views/modals/course_outline_modals.js
#: cms/static/js/views/utils/view_utils.js
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: common/static/common/js/components/utils/view_utils.js
#: cms/templates/js/add-xblock-component-menu-problem.underscore
#: cms/templates/js/add-xblock-component-menu.underscore
#: cms/templates/js/certificate-editor.underscore
@@ -139,6 +140,11 @@ msgstr "موافق"
#: cms/templates/js/group-configuration-editor.underscore
#: cms/templates/js/section-name-edit.underscore
#: cms/templates/js/xblock-string-field-editor.underscore
#: common/static/common/templates/discussion/new-post.underscore
#: common/static/common/templates/discussion/response-comment-edit.underscore
#: common/static/common/templates/discussion/thread-edit.underscore
#: common/static/common/templates/discussion/thread-response-edit.underscore
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
#: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore
msgid "Cancel"
msgstr "إلغاء"
@@ -148,17 +154,6 @@ msgstr "إلغاء"
#: cms/static/js/views/manage_users_and_roles.js
#: cms/static/js/views/show_textbook.js
#: common/static/js/vendor/ova/catch/js/catch.js
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-details.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/course-outline.underscore
#: cms/templates/js/course_grade_policy.underscore
#: cms/templates/js/group-configuration-details.underscore
#: cms/templates/js/group-configuration-editor.underscore
#: cms/templates/js/show-textbook.underscore
#: cms/templates/js/signatory-editor.underscore
#: cms/templates/js/xblock-outline.underscore
msgid "Delete"
msgstr "حذف"
@@ -233,14 +228,12 @@ msgstr "خطأ"
msgid "Save"
msgstr "حفظ"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: cms/static/js/views/modals/edit_xblock.js
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/signatory-editor.underscore
msgid "Close"
msgstr "إغلاق"
msgstr "إغلاق "
#: common/lib/xmodule/xmodule/js/src/annotatable/display.js
msgid "Show Annotations"
@@ -336,6 +329,8 @@ msgstr "لم يلبِّ مجموع نقاطك المعيار المطلوب لل
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
#: lms/static/coffee/src/staff_grading/staff_grading.js
#: common/static/common/templates/discussion/thread-response.underscore
#: common/static/common/templates/discussion/thread.underscore
#: lms/templates/verify_student/incourse_reverify.underscore
msgid "Submit"
msgstr "تقديم"
@@ -765,18 +760,10 @@ msgstr "خصائص المستند"
msgid "Edit HTML"
msgstr "تعديل لغة HTML"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: common/static/js/vendor/ova/catch/js/catch.js
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/content-group-details.underscore
#: cms/templates/js/course_info_handouts.underscore
#: cms/templates/js/group-configuration-details.underscore
#: cms/templates/js/show-textbook.underscore
#: cms/templates/js/signatory-details.underscore
#: cms/templates/js/xblock-string-field-editor.underscore
msgid "Edit"
msgstr "تعديل"
@@ -1177,11 +1164,9 @@ msgstr "مستند جديد"
msgid "New window"
msgstr "نافذة جديدة"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/paging-header.underscore
msgid "Next"
msgstr "التالي"
@@ -1531,12 +1516,9 @@ msgstr ""
"يبدو أن الرابط الذي أدخلته عبارة عن رابط خارجي، هل تريد إضافة البادئة "
"http:// اللازمة؟"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/signatory-details.underscore
#: cms/templates/js/signatory-editor.underscore
msgid "Title"
msgstr "العنوان"
@@ -2161,6 +2143,18 @@ msgstr "نأسف لحدوث مشكلة في حذف هذا التعليق. يُر
msgid "Are you sure you want to delete this response?"
msgstr "هل أنت واثق من أنّك تودّ حذف هذا الرد؟"
#: common/static/common/js/components/utils/view_utils.js
msgid "Required field."
msgstr ""
#: common/static/common/js/components/utils/view_utils.js
msgid "Please do not use any spaces in this field."
msgstr ""
#: common/static/common/js/components/utils/view_utils.js
msgid "Please do not use any spaces or special characters in this field."
msgstr ""
#: common/static/common/js/components/views/paging_header.js
msgid "Showing %(first_index)s out of %(num_items)s total"
msgstr "إظهار %(first_index)s من أصل %(num_items)s."
@@ -2360,6 +2354,7 @@ msgstr "تاريخ النشر"
#: common/static/js/vendor/ova/catch/js/catch.js
#: lms/static/js/courseware/credit_progress.js
#: common/static/common/templates/discussion/forum-actions.underscore
#: lms/templates/discovery/facet.underscore
#: lms/templates/edxnotes/note-item.underscore
msgid "More"
@@ -2439,21 +2434,34 @@ msgid "An unexpected error occurred. Please try again."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "last activity"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "open slots"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
#: lms/templates/edxnotes/tab-item.underscore
msgid "name"
msgstr "الاسم "
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "open_slots"
msgstr "open_slots"
#. Translators: This refers to the number of teams (a count of how many teams
#. there are)
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
msgid "team count"
msgstr "عدد أعضاء الفريق"
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/group-configuration-editor.underscore
msgid "Create"
msgstr "إنشاء "
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
msgid "Update"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
msgid "Team Name (Required) *"
msgstr ""
@@ -2478,6 +2486,7 @@ msgid "Language"
msgstr "اللغة"
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid ""
"The language that team members primarily use to communicate with each other."
msgstr ""
@@ -2488,6 +2497,7 @@ msgid "Country"
msgstr "البلد"
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "The country that team members primarily identify with."
msgstr ""
@@ -2520,20 +2530,48 @@ msgstr ""
msgid "You are not currently a member of any team."
msgstr ""
#. Translators: "and others" refers to fact that additional members of a team
#. exist that are not displayed.
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "and others"
msgstr ""
#. Translators: 'date' is a placeholder for a fuzzy, relative timestamp (see:
#. https://github.com/rmm5t/jquery-timeago)
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "Last Activity %(date)s"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "View %(span_start)s %(team_name)s %(span_end)s"
msgstr "مشاهدة %(span_start)s %(team_name)s %(span_end)s"
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "An error occurred. Try again."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
msgid "Leave this team?"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
msgid ""
"If you leave, you can no longer post in this team's discussions. Your place "
"will be available to another learner."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
#: lms/static/js/verify_student/views/reverify_view.js
#: lms/templates/verify_student/review_photos_step.underscore
msgid "Confirm"
msgstr "تأكيد"
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "You already belong to another team."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "This team is full."
msgstr ""
@@ -2555,6 +2593,10 @@ msgstr ""
msgid "teams"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Teams"
msgstr "الفِرَق"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"See all teams in your course, organized by topic. Join a team to collaborate"
@@ -2563,31 +2605,52 @@ msgstr ""
"تفضّل بالاطّلاع على جميع الفرق في مساقك، مرتّبةً بحسب الموضوع. وانضم إلى "
"أحدها للتعاون مع المتعلّمين الآخرين المهتمّين بالمجال نفسه مثلك."
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Teams"
msgstr "الفِرَق"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "My Team"
msgstr ""
#. Translators: sr_start and sr_end surround text meant only for screen
#. readers. The whole string will be shown to users as "Browse teams" if they
#. are using a screenreader, and "Browse" otherwise.
#. readers.
#. The whole string will be shown to users as "Browse teams" if they are using
#. a
#. screenreader, and "Browse" otherwise.
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Browse %(sr_start)s teams %(sr_end)s"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Create a new team if you can't find existing teams to join, or if you would "
"like to learn with friends you know."
msgid "Team Search"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Showing results for \"%(searchString)s\""
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Create a New Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Create a new team if you can't find an existing team to join, or if you "
"would like to learn with friends you know."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
#: lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
msgid "Edit Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"If you make significant changes, make sure you notify members of the team "
"before making these changes."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Search teams"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "All Topics"
msgstr ""
@@ -2614,15 +2677,27 @@ msgstr[3] "%(team_count)s فِرق"
msgstr[4] "%(team_count)s فِرق"
msgstr[5] "%(team_count)s فريقاً"
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "Topic"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "View Teams in the %(topic_name)s Topic"
msgstr "استعراض الفِرق في موضوع %(topic_name)s"
#. Translators: this string is shown at the bottom of the teams page
#. to find a team to join or else to create a new one. There are three
#. links that need to be included in the message:
#. 1. Browse teams in other topics
#. 2. search teams
#. 3. create a new team
#. Be careful to start each link with the appropriate start indicator
#. (e.g. {browse_span_start} for #1) and finish it with {span_end}.
#: lms/djangoapps/teams/static/teams/js/views/topic_teams.js
msgid ""
"Try {browse_span_start}browsing all teams{span_end} or "
"{search_span_start}searching team descriptions{span_end}. If you still can't"
" find a team to join, {create_span_start}create a new team in this "
"{browse_span_start}Browse teams in other topics{span_end} or "
"{search_span_start}search teams{span_end} in this topic. If you still can't "
"find a team to join, {create_span_start}create a new team in this "
"topic{span_end}."
msgstr ""
@@ -4098,11 +4173,6 @@ msgstr "التقاط صورة لبطاقتك الشخصية"
msgid "Review your info"
msgstr "مراجعة معلوماتك"
#: lms/static/js/verify_student/views/reverify_view.js
#: lms/templates/verify_student/review_photos_step.underscore
msgid "Confirm"
msgstr "تأكيد"
#: lms/static/js/verify_student/views/step_view.js
msgid "An error has occurred. Please try reloading the page."
msgstr "نأسف لحدوث خطأ. يُرجى محاولة إعادة تحميل الصفحة."
@@ -4690,7 +4760,7 @@ msgstr "جرى حذف ملفّك."
msgid "Date Added"
msgstr "تاريخ الإضافة "
#: cms/static/js/views/assets.js cms/templates/js/asset-library.underscore
#: cms/static/js/views/assets.js
msgid "Type"
msgstr "النوع"
@@ -5304,18 +5374,6 @@ msgstr ""
"لا يمكن أن يزيد مجموع الأحرف في حقلي المؤسسة ورمز المكتبة عن <%=limit%> "
"حرفًا."
#: cms/static/js/views/utils/view_utils.js
msgid "Required field."
msgstr "حقل مطلوب."
#: cms/static/js/views/utils/view_utils.js
msgid "Please do not use any spaces in this field."
msgstr "يُرجى عدم إدخال أي مسافات في هذا الحقل."
#: cms/static/js/views/utils/view_utils.js
msgid "Please do not use any spaces or special characters in this field."
msgstr "يُرجى عدم إدخال أي مسافات أو أحرف خاصة في هذا الحقل."
#: cms/static/js/views/utils/xblock_utils.js
msgid "component"
msgstr "مكوِّن"
@@ -5408,11 +5466,526 @@ msgstr "الإجراءات"
msgid "Due Date"
msgstr "تاريخ الاستحقاق"
#: cms/templates/js/paging-header.underscore
#: common/static/common/templates/components/paging-footer.underscore
#: common/static/common/templates/discussion/pagination.underscore
msgid "Previous"
msgstr ""
#: cms/templates/js/previous-video-upload-list.underscore
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
#: lms/templates/verify_student/enrollment_confirmation_step.underscore
msgid "Status"
msgstr "الحالة"
#: common/static/common/templates/image-modal.underscore
msgid "Large"
msgstr ""
#: common/static/common/templates/image-modal.underscore
msgid "Zoom In"
msgstr ""
#: common/static/common/templates/image-modal.underscore
msgid "Zoom Out"
msgstr ""
#: common/static/common/templates/components/paging-footer.underscore
msgid "Page number"
msgstr ""
#: common/static/common/templates/components/paging-footer.underscore
msgid "Enter the page number you'd like to quickly navigate to."
msgstr ""
#: common/static/common/templates/components/paging-header.underscore
msgid "Sorted by"
msgstr ""
#: common/static/common/templates/components/search-field.underscore
msgid "Clear search"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "DISCUSSION HOME:"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
#: lms/templates/commerce/provider.underscore
#: lms/templates/commerce/receipt.underscore
#: lms/templates/discovery/course_card.underscore
msgid "gettext("
msgstr "gettext("
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Find discussions"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Focus in on specific topics"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Search for specific posts"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Sort by date, vote, or comments"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Engage with posts"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Upvote posts and good responses"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Report Forum Misuse"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Follow posts for updates"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Receive updates"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Toggle Notifications Setting"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid ""
"Check this box to receive an email digest once a day notifying you about "
"new, unread activity from posts you are following."
msgstr ""
#: common/static/common/templates/discussion/forum-action-answer.underscore
msgid "Mark as Answer"
msgstr ""
#: common/static/common/templates/discussion/forum-action-answer.underscore
msgid "Unmark as Answer"
msgstr ""
#: common/static/common/templates/discussion/forum-action-close.underscore
msgid "Open"
msgstr ""
#: common/static/common/templates/discussion/forum-action-endorse.underscore
msgid "Endorse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-endorse.underscore
msgid "Unendorse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-follow.underscore
msgid "Follow"
msgstr ""
#: common/static/common/templates/discussion/forum-action-follow.underscore
msgid "Unfollow"
msgstr ""
#: common/static/common/templates/discussion/forum-action-pin.underscore
msgid "Pin"
msgstr ""
#: common/static/common/templates/discussion/forum-action-pin.underscore
msgid "Unpin"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Report abuse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Report"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Unreport"
msgstr ""
#: common/static/common/templates/discussion/forum-action-vote.underscore
msgid "Vote for this post,"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Visible To:"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "All Groups"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid ""
"Discussion admins, moderators, and TAs can make their posts visible to all "
"students or specify a single cohort."
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Title:"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Add a clear and descriptive title to encourage participation."
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Enter your question or comment"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "follow this post"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "post anonymously"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "post anonymously to classmates"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Add Post"
msgstr ""
#: common/static/common/templates/discussion/post-user-display.underscore
msgid "Community TA"
msgstr ""
#: common/static/common/templates/discussion/profile-thread.underscore
#: common/static/common/templates/discussion/thread.underscore
msgid "This thread is closed."
msgstr ""
#: common/static/common/templates/discussion/profile-thread.underscore
msgid "View discussion"
msgstr ""
#: common/static/common/templates/discussion/response-comment-edit.underscore
msgid "Editing comment"
msgstr ""
#: common/static/common/templates/discussion/response-comment-edit.underscore
msgid "Update comment"
msgstr ""
#: common/static/common/templates/discussion/response-comment-show.underscore
#, python-format
msgid "posted %(time_ago)s by %(author)s"
msgstr ""
#: common/static/common/templates/discussion/response-comment-show.underscore
#: common/static/common/templates/discussion/thread-response-show.underscore
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Reported"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Editing post"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Edit post title"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Update post"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "discussion"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "answered question"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "unanswered question"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Pinned"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "Following"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "By: Staff"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "By: Community TA"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#: common/static/common/templates/discussion/thread-response-show.underscore
msgid "fmt"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#, python-format
msgid ""
"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s "
"unread comments)%(span_close)s"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#, python-format
msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-edit.underscore
msgid "Editing response"
msgstr ""
#: common/static/common/templates/discussion/thread-response-edit.underscore
msgid "Update response"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "marked as answer %(time_ago)s by %(user)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "marked as answer %(time_ago)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "endorsed %(time_ago)s by %(user)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "endorsed %(time_ago)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response.underscore
msgid "fmts"
msgstr ""
#: common/static/common/templates/discussion/thread-response.underscore
msgid "Add a comment"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "This post is visible only to %(group_name)s."
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
msgid "This post is visible to everyone."
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "%(post_type)s posted %(time_ago)s by %(author)s"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Closed"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "Related to: %(courseware_title_linked)s"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Post type:"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Question"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Discussion"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid ""
"Questions raise issues that need answers. Discussions share ideas and start "
"conversations."
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Add a Response"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Post a response:"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Expand discussion"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Collapse discussion"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Topic Area:"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Discussion topics; current selection is:"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Filter topics"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Add your post to a relevant topic to help others find it."
msgstr ""
#: common/static/common/templates/discussion/user-profile.underscore
msgid "Active Threads"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates.underscore
msgid "username or email"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "No results"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Course Key"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Download URL"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Grade"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Last Updated"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Download the user's certificate"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Not available"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Regenerate"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Regenerate the user's certificate"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Your team could not be created."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Your team could not be updated."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid ""
"Enter information to describe your team. You cannot change these details "
"after you create the team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Optional Characteristics"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid ""
"Help other learners decide whether to join your team by specifying some "
"characteristics for your team. Choose carefully, because fewer people might "
"be interested in joining your team if it seems too restrictive."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Create team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Update team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel team creating."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel team updating."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-actions.underscore
msgid "Are you having trouble finding a team to join?"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
msgid "Join Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "New Post"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team Details"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "You are a member of this team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team member profiles"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team capacity"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "country"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "language"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Leave Team"
msgstr ""
#: lms/static/js/fixtures/donation.underscore
#: lms/templates/dashboard/donation.underscore
msgid "Donate"
msgstr "تبرَّع"
#: lms/templates/ccx/schedule.underscore
msgid "Expand All"
msgstr ""
@@ -5453,12 +6026,6 @@ msgstr ""
msgid "Subsection"
msgstr ""
#: lms/templates/commerce/provider.underscore
#: lms/templates/commerce/receipt.underscore
#: lms/templates/discovery/course_card.underscore
msgid "gettext("
msgstr "gettext("
#: lms/templates/commerce/provider.underscore
#, python-format
msgid "<img src='%s' alt='%s'></image>"
@@ -5554,10 +6121,6 @@ msgstr ""
msgid "End My Exam"
msgstr ""
#: lms/templates/dashboard/donation.underscore
msgid "Donate"
msgstr "تبرَّع"
#: lms/templates/discovery/course_card.underscore
msgid "LEARN MORE"
msgstr "اعرف المزيد"
@@ -6566,6 +7129,16 @@ msgstr "استخدم خاصية السحب والإفلات أو اضغط هنا
msgid "status"
msgstr "الحالة"
#: cms/templates/js/add-xblock-component-button.underscore
msgid "Add Component:"
msgstr ""
#: cms/templates/js/add-xblock-component-menu-problem.underscore
#: cms/templates/js/add-xblock-component-menu.underscore
#, python-format
msgid "%(type)s Component Template Menu"
msgstr ""
#: cms/templates/js/add-xblock-component-menu-problem.underscore
msgid "Common Problem Types"
msgstr "المسائل الشائعة"
@@ -6640,6 +7213,11 @@ msgstr "الرمز التعريفي"
msgid "Certificate Details"
msgstr "تفاصيل الشهادة"
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
msgid "Course Title"
msgstr ""
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
msgid "Course Title Override"
@@ -6686,19 +7264,13 @@ msgstr ""
"الحقل فارغًا لاستخدام العنوان الرسمي للمساق."
#: cms/templates/js/certificate-editor.underscore
msgid "Add Signatory"
msgstr "إضافة مُوَقّع"
msgid "Add Additional Signatory"
msgstr ""
#: cms/templates/js/certificate-editor.underscore
msgid "(Up to 4 signatories are allowed for a certificate)"
msgstr "(يمكن إضافة 4 موقِّعين كحد أقصى لكل شهادة)"
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/group-configuration-editor.underscore
msgid "Create"
msgstr "إنشاء "
#: cms/templates/js/certificate-web-preview.underscore
msgid "Choose mode"
msgstr "اختر الوضع"
@@ -7132,10 +7704,6 @@ msgstr "لم تُضِف بعد أي كتب إلى هذا المساق."
msgid "Add your first textbook"
msgstr "أضِف أوّل كتاب لك."
#: cms/templates/js/paging-header.underscore
msgid "Previous"
msgstr "السابق"
#: cms/templates/js/previous-video-upload-list.underscore
msgid "Previous Uploads"
msgstr "تحميلات سابقة"

Binary file not shown.

View File

@@ -37,8 +37,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-24 22:03+0000\n"
"PO-Revision-Date: 2015-08-24 22:03:48.240461\n"
"POT-Creation-Date: 2015-09-04 14:15+0000\n"
"PO-Revision-Date: 2015-09-04 14:15:47.324123\n"
"Last-Translator: \n"
"Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n"
"MIME-Version: 1.0\n"
@@ -1418,10 +1418,6 @@ msgstr "çörréçt Ⱡ'σяєм ιρѕυм #"
msgid "incorrect"
msgstr "ïnçörréçt Ⱡ'σяєм ιρѕυм ∂σł#"
#: common/lib/capa/capa/inputtypes.py
msgid "partially correct"
msgstr "pärtïällý çörréçt Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
#: common/lib/capa/capa/inputtypes.py
msgid "incomplete"
msgstr "ïnçömplété Ⱡ'σяєм ιρѕυм ∂σłσ#"
@@ -1444,10 +1440,6 @@ msgstr "Thïs ïs çörréçt. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
msgid "This is incorrect."
msgstr "Thïs ïs ïnçörréçt. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"
#: common/lib/capa/capa/inputtypes.py
msgid "This is partially correct."
msgstr "Thïs ïs pärtïällý çörréçt. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#"
#: common/lib/capa/capa/inputtypes.py
msgid "This is unanswered."
msgstr "Thïs ïs ünänswéréd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт,#"
@@ -5858,10 +5850,20 @@ msgid "{month} {day}, {year}"
msgstr "{month} {day}, {year} Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: lms/djangoapps/certificates/views/webview.py
msgid "a course of study offered by {partner_name}, through {platform_name}."
msgid ""
"a course of study offered by {partner_short_name}, an online learning "
"initiative of {partner_long_name} through {platform_name}."
msgstr ""
"ä çöürsé öf stüdý öfféréd ßý {partner_name}, thröügh {platform_name}. Ⱡ'σяєм"
" ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
"ä çöürsé öf stüdý öfféréd ßý {partner_short_name}, än önlïné léärnïng "
"ïnïtïätïvé öf {partner_long_name} thröügh {platform_name}. Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"a course of study offered by {partner_short_name}, through {platform_name}."
msgstr ""
"ä çöürsé öf stüdý öfféréd ßý {partner_short_name}, thröügh {platform_name}. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#. Translators: Accomplishments describe the awards/certifications obtained by
#. students on this platform
@@ -5995,19 +5997,19 @@ msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"This is a valid {platform_name} certificate for {user_name}, who "
"participated in {partner_name} {course_number}"
"participated in {partner_short_name} {course_number}"
msgstr ""
"Thïs ïs ä välïd {platform_name} çértïfïçäté för {user_name}, whö "
"pärtïçïpätéd ïn {partner_name} {course_number} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
"pärtïçïpätéd ïn {partner_short_name} {course_number} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя #"
#. Translators: This text is bound to the HTML 'title' element of the page
#. and appears in the browser title bar
#: lms/djangoapps/certificates/views/webview.py
msgid "{partner_name} {course_number} Certificate | {platform_name}"
msgid "{partner_short_name} {course_number} Certificate | {platform_name}"
msgstr ""
"{partner_name} {course_number} Çértïfïçäté | {platform_name} Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕ#"
"{partner_short_name} {course_number} Çértïfïçäté | {platform_name} Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#"
#. Translators: This text fragment appears after the student's name
#. (displayed in a large font) on the certificate
@@ -6194,6 +6196,15 @@ msgstr ""
"Ìf ýöür çöürsé döés nöt äppéär ön ýöür däshßöärd, çöntäçt "
"{payment_support_link}. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "{course_id} is not a valid course key."
msgstr ""
"{course_id} ïs nöt ä välïd çöürsé kéý. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "Course {course_id} does not exist."
msgstr "Çöürsé {course_id} döés nöt éxïst. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#"
#: lms/djangoapps/course_wiki/tab.py lms/djangoapps/course_wiki/views.py
#: lms/templates/wiki/base.html
msgid "Wiki"
@@ -6804,6 +6815,35 @@ msgstr "Ûsérnämé {user} älréädý éxïsts. Ⱡ'σяєм ιρѕυм ∂σ
msgid "File is not attached."
msgstr "Fïlé ïs nöt ättäçhéd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: lms/djangoapps/instructor/views/api.py
msgid "Could not find problem with this location."
msgstr ""
"Çöüld nöt fïnd prößlém wïth thïs löçätïön. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"The problem responses report is being created. To view the status of the "
"report, see Pending Tasks below."
msgstr ""
"Thé prößlém réspönsés répört ïs ßéïng çréätéd. Tö vïéw thé stätüs öf thé "
"répört, séé Péndïng Täsks ßélöw. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт #"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A problem responses report generation task is already in progress. Check the"
" 'Pending Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
msgstr ""
"À prößlém réspönsés répört générätïön täsk ïs älréädý ïn prögréss. Çhéçk thé"
" 'Péndïng Täsks' täßlé för thé stätüs öf thé täsk. Whén çömplétéd, thé "
"répört wïll ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. Ⱡ'σяєм ιρѕυм ∂σłσя"
" ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт"
" łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ "
"єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ "
"αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ "
υgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢#"
#: lms/djangoapps/instructor/views/api.py
msgid "Invoice number '{num}' does not exist."
msgstr ""
@@ -7334,6 +7374,10 @@ msgstr ""
"ÇöürséMödé prïçé üpdätéd süççéssfüllý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυ#"
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "No end date set"
msgstr "Nö énd däté sét Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#"
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "Enrollment data is now available in {dashboard_link}."
msgstr ""
@@ -7439,21 +7483,6 @@ msgstr "Éxtérnäl émäïl Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#"
msgid "Grades for assignment \"{name}\""
msgstr "Grädés för ässïgnmént \"{name}\" Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#"
#: lms/djangoapps/instructor/views/legacy.py
msgid "Found {num} records to dump."
msgstr "Föünd {num} réçörds tö dümp. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#"
#: lms/djangoapps/instructor/views/legacy.py
msgid "Couldn't find module with that urlname."
msgstr ""
"Çöüldn't fïnd mödülé wïth thät ürlnämé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя#"
#: lms/djangoapps/instructor/views/legacy.py
msgid "Student state for problem {problem}"
msgstr ""
"Stüdént stäté för prößlém {problem} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#"
#: lms/djangoapps/instructor/views/legacy.py
msgid "Grades from {course_id}"
msgstr "Grädés fröm {course_id} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#"
@@ -7656,6 +7685,12 @@ msgstr "délétéd Ⱡ'σяєм ιρѕυм #"
msgid "emailed"
msgstr "émäïléd Ⱡ'σяєм ιρѕυм #"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr "générätéd Ⱡ'σяєм ιρѕυм ∂σł#"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -7668,12 +7703,6 @@ msgstr "grädéd Ⱡ'σяєм ιρѕυ#"
msgid "problem distribution graded"
msgstr "prößlém dïstrïßütïön grädéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr "générätéd Ⱡ'σяєм ιρѕυм ∂σł#"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -10900,18 +10929,6 @@ msgstr ""
"Nö dätä prövïdéd för üsér préférénçé üpdäté Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
#: openedx/core/lib/api/paginators.py
msgid "Page is not 'last', nor can it be converted to an int."
msgstr ""
"Pägé ïs nöt 'läst', nör çän ït ßé çönvértéd tö än ïnt. Ⱡ'σяєм ιρѕυм ∂σłσя "
"ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: openedx/core/lib/api/paginators.py
#, python-format
msgid "Invalid page (%(page_number)s): %(message)s"
msgstr ""
"Ìnvälïd pägé (%(page_number)s): %(message)s Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#"
#: openedx/core/lib/api/view_utils.py
msgid "This value is invalid."
msgstr "Thïs välüé ïs ïnvälïd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢#"
@@ -14596,8 +14613,12 @@ msgid "Section:"
msgstr "Séçtïön: Ⱡ'σяєм ιρѕυм ∂#"
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid "Problem urlname:"
msgstr "Prößlém ürlnämé: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
msgid ""
"To download a CSV listing student responses to a given problem, visit the "
"Data Download section of the Instructor Dashboard."
msgstr ""
"Tö döwnlöäd ä ÇSV lïstïng stüdént réspönsés tö ä gïvén prößlém, vïsït thé "
"Dätä Döwnlöäd séçtïön öf thé Ìnstrüçtör Däshßöärd. Ⱡ'σяєм ι#"
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid ""
@@ -16947,6 +16968,29 @@ msgstr ""
"Généräté Pröçtöréd Éxäm Résülts Répört Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя#"
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"To generate a CSV file that lists all student answers to a given problem, "
"enter the location of the problem (from its Staff Debug Info)."
msgstr ""
"Tö généräté ä ÇSV fïlé thät lïsts äll stüdént änswérs tö ä gïvén prößlém, "
"éntér thé löçätïön öf thé prößlém (fröm ïts Stäff Déßüg Ìnfö). Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт łαвσя#"
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Problem location: "
msgstr "Prößlém löçätïön: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Download a CSV of problem responses"
msgstr ""
"Döwnlöäd ä ÇSV öf prößlém réspönsés Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#"
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"For smaller courses, click to list profile information for enrolled students"

View File

@@ -26,8 +26,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-24 22:03+0000\n"
"PO-Revision-Date: 2015-08-24 22:03:48.948707\n"
"POT-Creation-Date: 2015-09-04 14:15+0000\n"
"PO-Revision-Date: 2015-09-04 14:15:47.640544\n"
"Last-Translator: \n"
"Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n"
"MIME-Version: 1.0\n"
@@ -73,8 +73,8 @@ msgstr "ÖK Ⱡ'σя#"
#: cms/static/js/views/show_textbook.js cms/static/js/views/validation.js
#: cms/static/js/views/modals/base_modal.js
#: cms/static/js/views/modals/course_outline_modals.js
#: cms/static/js/views/utils/view_utils.js
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: common/static/common/js/components/utils/view_utils.js
#: cms/templates/js/add-xblock-component-menu-problem.underscore
#: cms/templates/js/add-xblock-component-menu.underscore
#: cms/templates/js/certificate-editor.underscore
@@ -89,6 +89,7 @@ msgstr "ÖK Ⱡ'σя#"
#: common/static/common/templates/discussion/response-comment-edit.underscore
#: common/static/common/templates/discussion/thread-edit.underscore
#: common/static/common/templates/discussion/thread-response-edit.underscore
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
#: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore
msgid "Cancel"
msgstr "Çänçél Ⱡ'σяєм ιρѕυ#"
@@ -2160,6 +2161,22 @@ msgstr ""
"Àré ýöü süré ýöü wänt tö délété thïs réspönsé? Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя α#"
#: common/static/common/js/components/utils/view_utils.js
msgid "Required field."
msgstr "Réqüïréd fïéld. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#"
#: common/static/common/js/components/utils/view_utils.js
msgid "Please do not use any spaces in this field."
msgstr ""
"Pléäsé dö nöt üsé äný späçés ïn thïs fïéld. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
#: common/static/common/js/components/utils/view_utils.js
msgid "Please do not use any spaces or special characters in this field."
msgstr ""
"Pléäsé dö nöt üsé äný späçés ör spéçïäl çhäräçtérs ïn thïs fïéld. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: common/static/common/js/components/views/paging_header.js
msgid "Showing %(first_index)s out of %(num_items)s total"
msgstr ""
@@ -2365,6 +2382,7 @@ msgid "Public"
msgstr "Püßlïç Ⱡ'σяєм ιρѕυ#"
#: common/static/js/vendor/ova/catch/js/catch.js
#: common/static/common/templates/components/search-field.underscore
#: lms/djangoapps/support/static/support/templates/certificates.underscore
msgid "Search"
msgstr "Séärçh Ⱡ'σяєм ιρѕυ#"
@@ -2429,21 +2447,35 @@ msgstr ""
"αмєт, ¢σηѕє¢тєтυя α#"
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "last activity"
msgstr "läst äçtïvïtý Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "open slots"
msgstr "öpén slöts Ⱡ'σяєм ιρѕυм ∂σłσ#"
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
#: lms/templates/edxnotes/tab-item.underscore
msgid "name"
msgstr "nämé Ⱡ'σяєм ι#"
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "open_slots"
msgstr "öpén_slöts Ⱡ'σяєм ιρѕυм ∂σłσ#"
#. Translators: This refers to the number of teams (a count of how many teams
#. there are)
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
msgid "team count"
msgstr "téäm çöünt Ⱡ'σяєм ιρѕυм ∂σłσ#"
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/group-configuration-editor.underscore
msgid "Create"
msgstr "Çréäté Ⱡ'σяєм ιρѕυ#"
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
msgid "Update"
msgstr "Ûpdäté Ⱡ'σяєм ιρѕυ#"
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
msgid "Team Name (Required) *"
msgstr "Téäm Nämé (Réqüïréd) * Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢#"
@@ -2530,22 +2562,52 @@ msgstr ""
"Ýöü äré nöt çürréntlý ä mémßér öf äný téäm. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
#. Translators: "and others" refers to fact that additional members of a team
#. exist that are not displayed.
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "and others"
msgstr "änd öthérs Ⱡ'σяєм ιρѕυм ∂σłσ#"
#. Translators: 'date' is a placeholder for a fuzzy, relative timestamp (see:
#. https://github.com/rmm5t/jquery-timeago)
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "Last Activity %(date)s"
msgstr "Läst Àçtïvïtý %(date)s Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "View %(span_start)s %(team_name)s %(span_end)s"
msgstr ""
"Vïéw %(span_start)s %(team_name)s %(span_end)s Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "An error occurred. Try again."
msgstr "Àn érrör öççürréd. Trý ägäïn. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#"
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
msgid "Leave this team?"
msgstr "Léävé thïs téäm? Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
msgid ""
"If you leave, you can no longer post in this team's discussions. Your place "
"will be available to another learner."
msgstr ""
"Ìf ýöü léävé, ýöü çän nö löngér pöst ïn thïs téäm's dïsçüssïöns. Ýöür pläçé "
"wïll ßé äväïläßlé tö änöthér léärnér. Ⱡ'σяєм ιρѕυм ∂σłσ#"
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
#: lms/static/js/verify_student/views/reverify_view.js
#: lms/templates/verify_student/review_photos_step.underscore
msgid "Confirm"
msgstr "Çönfïrm Ⱡ'σяєм ιρѕυм #"
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "You already belong to another team."
msgstr ""
"Ýöü älréädý ßélöng tö änöthér téäm. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#"
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "This team is full."
msgstr "Thïs téäm ïs füll. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"
@@ -2565,6 +2627,10 @@ msgstr "Àll téäms Ⱡ'σяєм ιρѕυм ∂σł#"
msgid "teams"
msgstr "téäms Ⱡ'σяєм ιρѕ#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Teams"
msgstr "Téäms Ⱡ'σяєм ιρѕ#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"See all teams in your course, organized by topic. Join a team to collaborate"
@@ -2579,33 +2645,57 @@ msgstr ""
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Teams"
msgstr "Téäms Ⱡ'σяєм ιρѕ#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "My Team"
msgstr "Mý Téäm Ⱡ'σяєм ιρѕυм #"
#. Translators: sr_start and sr_end surround text meant only for screen
#. readers. The whole string will be shown to users as "Browse teams" if they
#. are using a screenreader, and "Browse" otherwise.
#. readers.
#. The whole string will be shown to users as "Browse teams" if they are using
#. a
#. screenreader, and "Browse" otherwise.
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Browse %(sr_start)s teams %(sr_end)s"
msgstr "Bröwsé %(sr_start)s téäms %(sr_end)s Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Create a new team if you can't find existing teams to join, or if you would "
"like to learn with friends you know."
msgid "Team Search"
msgstr "Téäm Séärçh Ⱡ'σяєм ιρѕυм ∂σłσя #"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Showing results for \"%(searchString)s\""
msgstr ""
"Çréäté ä néw téäm ïf ýöü çän't fïnd éxïstïng téäms tö jöïn, ör ïf ýöü wöüld "
"lïké tö léärn wïth frïénds ýöü knöw. Ⱡ'σяєм ιρѕυм ∂σłσя#"
"Shöwïng résülts för \"%(searchString)s\" Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Create a New Team"
msgstr "Çréäté ä Néw Téäm Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Create a new team if you can't find an existing team to join, or if you "
"would like to learn with friends you know."
msgstr ""
"Çréäté ä néw téäm ïf ýöü çän't fïnd än éxïstïng téäm tö jöïn, ör ïf ýöü "
"wöüld lïké tö léärn wïth frïénds ýöü knöw. Ⱡ'σяєм ιρѕυм ∂σł#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
#: lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
msgid "Edit Team"
msgstr "Édït Téäm Ⱡ'σяєм ιρѕυм ∂σł#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"If you make significant changes, make sure you notify members of the team "
"before making these changes."
msgstr ""
"Ìf ýöü mäké sïgnïfïçänt çhängés, mäké süré ýöü nötïfý mémßérs öf thé téäm "
"ßéföré mäkïng thésé çhängés. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Search teams"
msgstr "Séärçh téäms Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "All Topics"
msgstr "Àll Töpïçs Ⱡ'σяєм ιρѕυм ∂σłσ#"
@@ -2634,27 +2724,39 @@ msgid_plural "%(team_count)s Teams"
msgstr[0] "%(team_count)s Téäm Ⱡ'σяєм ιρѕυм ∂#"
msgstr[1] "%(team_count)s Téäms Ⱡ'σяєм ιρѕυм ∂σł#"
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "Topic"
msgstr "Töpïç Ⱡ'σяєм ιρѕ#"
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "View Teams in the %(topic_name)s Topic"
msgstr ""
"Vïéw Téäms ïn thé %(topic_name)s Töpïç Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#"
#. Translators: this string is shown at the bottom of the teams page
#. to find a team to join or else to create a new one. There are three
#. links that need to be included in the message:
#. 1. Browse teams in other topics
#. 2. search teams
#. 3. create a new team
#. Be careful to start each link with the appropriate start indicator
#. (e.g. {browse_span_start} for #1) and finish it with {span_end}.
#: lms/djangoapps/teams/static/teams/js/views/topic_teams.js
msgid ""
"Try {browse_span_start}browsing all teams{span_end} or "
"{search_span_start}searching team descriptions{span_end}. If you still can't"
" find a team to join, {create_span_start}create a new team in this "
"{browse_span_start}Browse teams in other topics{span_end} or "
"{search_span_start}search teams{span_end} in this topic. If you still can't "
"find a team to join, {create_span_start}create a new team in this "
"topic{span_end}."
msgstr ""
"Trý {browse_span_start}ßröwsïng äll téäms{span_end} ör "
"{search_span_start}séärçhïng téäm désçrïptïöns{span_end}. Ìf ýöü stïll çän't"
" fïnd ä téäm tö jöïn, {create_span_start}çréäté ä néw téäm ïn thïs "
"{browse_span_start}Bröwsé téäms ïn öthér töpïçs{span_end} ör "
"{search_span_start}séärçh téäms{span_end} ïn thïs töpïç. Ìf ýöü stïll çän't "
"fïnd ä téäm tö jöïn, {create_span_start}çréäté ä néw téäm ïn thïs "
"töpïç{span_end}. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, "
"ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм "
"α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ "
"єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє"
" νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт "
"¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂#"
"¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αη#"
#: lms/djangoapps/teams/static/teams/js/views/topics.js
msgid "All topics"
@@ -4343,11 +4445,6 @@ msgstr "Täké ä phötö öf ýöür ÌD Ⱡ'σяєм ιρѕυм ∂σłσя ѕ
msgid "Review your info"
msgstr "Révïéw ýöür ïnfö Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
#: lms/static/js/verify_student/views/reverify_view.js
#: lms/templates/verify_student/review_photos_step.underscore
msgid "Confirm"
msgstr "Çönfïrm Ⱡ'σяєм ιρѕυм #"
#: lms/static/js/verify_student/views/step_view.js
msgid "An error has occurred. Please try reloading the page."
msgstr ""
@@ -5730,22 +5827,6 @@ msgstr ""
"Thé çömßïnéd léngth öf thé örgänïzätïön änd lïßrärý çödé fïélds çännöt ßé "
"möré thän <%=limit%> çhäräçtérs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"
#: cms/static/js/views/utils/view_utils.js
msgid "Required field."
msgstr "Réqüïréd fïéld. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#"
#: cms/static/js/views/utils/view_utils.js
msgid "Please do not use any spaces in this field."
msgstr ""
"Pléäsé dö nöt üsé äný späçés ïn thïs fïéld. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
#: cms/static/js/views/utils/view_utils.js
msgid "Please do not use any spaces or special characters in this field."
msgstr ""
"Pléäsé dö nöt üsé äný späçés ör spéçïäl çhäräçtérs ïn thïs fïéld. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: cms/static/js/views/utils/xblock_utils.js
msgid "component"
msgstr "çömpönént Ⱡ'σяєм ιρѕυм ∂σł#"
@@ -5877,6 +5958,14 @@ msgstr ""
"Éntér thé pägé nümßér ýöü'd lïké tö qüïçklý nävïgäté tö. Ⱡ'σяєм ιρѕυм ∂σłσя "
"ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: common/static/common/templates/components/paging-header.underscore
msgid "Sorted by"
msgstr "Sörtéd ßý Ⱡ'σяєм ιρѕυм ∂σł#"
#: common/static/common/templates/components/search-field.underscore
msgid "Clear search"
msgstr "Çléär séärçh Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "DISCUSSION HOME:"
msgstr "DÌSÇÛSSÌÖN HÖMÉ: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
@@ -6296,8 +6385,12 @@ msgstr ""
"Régénéräté thé üsér's çértïfïçäté Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#"
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Your team could not be created!"
msgstr "Ýöür téäm çöüld nöt ßé çréätéd! Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
msgid "Your team could not be created."
msgstr "Ýöür téäm çöüld nöt ßé çréätéd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Your team could not be updated."
msgstr "Ýöür téäm çöüld nöt ßé üpdätéd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid ""
@@ -6327,15 +6420,20 @@ msgstr ""
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρт#"
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "{primaryButtonTitle} {span_start}a new team{span_end}"
msgstr ""
"{primaryButtonTitle} {span_start}ä néw téäm{span_end} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт"
" αмєт, #"
msgid "Create team."
msgstr "Çréäté téäm. Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel {span_start}a new team{span_end}"
msgstr ""
"Çänçél {span_start}ä néw téäm{span_end} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#"
msgid "Update team."
msgstr "Ûpdäté téäm. Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel team creating."
msgstr "Çänçél téäm çréätïng. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel team updating."
msgstr "Çänçél téäm üpdätïng. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: lms/djangoapps/teams/static/teams/templates/team-actions.underscore
msgid "Are you having trouble finding a team to join?"
@@ -6343,7 +6441,7 @@ msgstr ""
"Àré ýöü hävïng tröüßlé fïndïng ä téäm tö jöïn? Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя α#"
#: lms/djangoapps/teams/static/teams/templates/team-join.underscore
#: lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
msgid "Join Team"
msgstr "Jöïn Téäm Ⱡ'σяєм ιρѕυм ∂σł#"
@@ -7683,6 +7781,16 @@ msgstr ""
msgid "status"
msgstr "stätüs Ⱡ'σяєм ιρѕυ#"
#: cms/templates/js/add-xblock-component-button.underscore
msgid "Add Component:"
msgstr "Àdd Çömpönént: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#"
#: cms/templates/js/add-xblock-component-menu-problem.underscore
#: cms/templates/js/add-xblock-component-menu.underscore
#, python-format
msgid "%(type)s Component Template Menu"
msgstr "%(type)s Çömpönént Témpläté Ménü Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#"
#: cms/templates/js/add-xblock-component-menu-problem.underscore
msgid "Common Problem Types"
msgstr "Çömmön Prößlém Týpés Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
@@ -7761,6 +7869,11 @@ msgstr "ÌD Ⱡ'σя#"
msgid "Certificate Details"
msgstr "Çértïfïçäté Détäïls Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт,#"
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
msgid "Course Title"
msgstr "Çöürsé Tïtlé Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
msgid "Course Title Override"
@@ -7807,8 +7920,8 @@ msgstr ""
"çértïfïçätés. Léävé ßlänk tö üsé thé öffïçïäl çöürsé tïtlé. Ⱡ'σяєм #"
#: cms/templates/js/certificate-editor.underscore
msgid "Add Signatory"
msgstr "Àdd Sïgnätörý Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
msgid "Add Additional Signatory"
msgstr "Àdd Àddïtïönäl Sïgnätörý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢ση#"
#: cms/templates/js/certificate-editor.underscore
msgid "(Up to 4 signatories are allowed for a certificate)"
@@ -7816,12 +7929,6 @@ msgstr ""
"(Ûp tö 4 sïgnätörïés äré ällöwéd för ä çértïfïçäté) Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя α#"
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/group-configuration-editor.underscore
msgid "Create"
msgstr "Çréäté Ⱡ'σяєм ιρѕυ#"
#: cms/templates/js/certificate-web-preview.underscore
msgid "Choose mode"
msgstr "Çhöösé mödé Ⱡ'σяєм ιρѕυм ∂σłσя #"

View File

@@ -172,7 +172,7 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-21 14:18+0000\n"
"POT-Creation-Date: 2015-09-04 14:07+0000\n"
"PO-Revision-Date: 2015-06-29 17:10+0000\n"
"Last-Translator: Cristian Salamea <ovnicraft@gmail.com>\n"
"Language-Team: Spanish (Latin America) (http://www.transifex.com/open-edx/edx-platform/language/es_419/)\n"
@@ -1413,10 +1413,6 @@ msgstr "Correcto"
msgid "incorrect"
msgstr "incorrecto"
#: common/lib/capa/capa/inputtypes.py
msgid "partially correct"
msgstr "parcialmente correcto"
#: common/lib/capa/capa/inputtypes.py
msgid "incomplete"
msgstr "Incompleto"
@@ -1439,10 +1435,6 @@ msgstr "Esto es correcto."
msgid "This is incorrect."
msgstr "Esto es incorrecto."
#: common/lib/capa/capa/inputtypes.py
msgid "This is partially correct."
msgstr "Esto es parcialmente correcto."
#: common/lib/capa/capa/inputtypes.py
msgid "This is unanswered."
msgstr "Esto no ha sido respondido."
@@ -5325,8 +5317,15 @@ msgid "{month} {day}, {year}"
msgstr "{day} de {month}, {year}"
#: lms/djangoapps/certificates/views/webview.py
msgid "a course of study offered by {partner_name}, through {platform_name}."
msgstr "curso ofrecido por {partner_name}, a través de {platform_name}."
msgid ""
"a course of study offered by {partner_short_name}, an online learning "
"initiative of {partner_long_name} through {platform_name}."
msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"a course of study offered by {partner_short_name}, through {platform_name}."
msgstr ""
#. Translators: Accomplishments describe the awards/certifications obtained by
#. students on this platform
@@ -5440,16 +5439,14 @@ msgstr "{platform_name} reconoce el siguiente logro al estudiante"
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"This is a valid {platform_name} certificate for {user_name}, who "
"participated in {partner_name} {course_number}"
"participated in {partner_short_name} {course_number}"
msgstr ""
"Este es un certificado válido de {platform_name} para el usuario "
"{user_name}, quién participó en el curso {partner_name} {course_number}"
#. Translators: This text is bound to the HTML 'title' element of the page
#. and appears in the browser title bar
#: lms/djangoapps/certificates/views/webview.py
msgid "{partner_name} {course_number} Certificate | {platform_name}"
msgstr "Certificado para {partner_name} {course_number} en {platform_name}"
msgid "{partner_short_name} {course_number} Certificate | {platform_name}"
msgstr ""
#. Translators: This text fragment appears after the student's name
#. (displayed in a large font) on the certificate
@@ -5616,6 +5613,14 @@ msgstr ""
"Si su curso no aparece en el panel de control, contacte a "
"{payment_support_link}."
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "{course_id} is not a valid course key."
msgstr ""
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "Course {course_id} does not exist."
msgstr ""
#: lms/djangoapps/course_wiki/tab.py lms/djangoapps/course_wiki/views.py
#: lms/templates/wiki/base.html
msgid "Wiki"
@@ -6170,6 +6175,23 @@ msgstr "Nombre de usuario {user} ya existe."
msgid "File is not attached."
msgstr "Archivo no adjuntado."
#: lms/djangoapps/instructor/views/api.py
msgid "Could not find problem with this location."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"The problem responses report is being created. To view the status of the "
"report, see Pending Tasks below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A problem responses report generation task is already in progress. Check the"
" 'Pending Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid "Invoice number '{num}' does not exist."
msgstr "La factura número '{num}' no existe."
@@ -6613,6 +6635,10 @@ msgstr "El modo de curso con slug ({mode_slug}) no existe."
msgid "CourseMode price updated successfully"
msgstr "Se actualizó correctamente el precio para el modo de curso."
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "No end date set"
msgstr ""
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "Enrollment data is now available in {dashboard_link}."
msgstr "Los datos de inscripciones ya están disponibles en {dashboard_link}."
@@ -6712,18 +6738,6 @@ msgstr "email externo"
msgid "Grades for assignment \"{name}\""
msgstr "Calificaciones para la tarea \"{name}\""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Found {num} records to dump."
msgstr "Se encontraron {num} registros para exportar."
#: lms/djangoapps/instructor/views/legacy.py
msgid "Couldn't find module with that urlname."
msgstr "No se ha encontrado ningún módulo con esa url."
#: lms/djangoapps/instructor/views/legacy.py
msgid "Student state for problem {problem}"
msgstr "Estado del estudiante para el problema {problem}"
#: lms/djangoapps/instructor/views/legacy.py
msgid "Grades from {course_id}"
msgstr "Calificaciones de {course_id}"
@@ -6903,6 +6917,12 @@ msgstr "borrado"
msgid "emailed"
msgstr "enviado al correo electrónico"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr "generado"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -6915,12 +6935,6 @@ msgstr "calificado"
msgid "problem distribution graded"
msgstr "Distribución de calificaciones del problema"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr "generado"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -8607,12 +8621,12 @@ msgid "course_id must be provided"
msgstr "Debe suministrar un ID de curso"
#: lms/djangoapps/teams/views.py
msgid "The supplied topic id {topic_id} is not valid"
msgstr "El ID de tema proporcionado {topic_id} no es válido"
msgid "text_search and order_by cannot be provided together"
msgstr ""
#: lms/djangoapps/teams/views.py
msgid "text_search is not yet supported."
msgstr "text_search actualmente no está soportado"
msgid "The supplied topic id {topic_id} is not valid"
msgstr "El ID de tema proporcionado {topic_id} no es válido"
#. Translators: 'ordering' is a string describing a way
#. of ordering a list. For example, {ordering} may be
@@ -10466,6 +10480,10 @@ msgstr "Ayuda"
msgid "Sign Out"
msgstr "Cerrar sesión"
#: common/lib/capa/capa/templates/codeinput.html
msgid "{programming_language} editor"
msgstr ""
#: common/templates/license.html
msgid "All Rights Reserved"
msgstr "Todos los Derechos Reservados"
@@ -13181,8 +13199,10 @@ msgid "Section:"
msgstr "Sección:"
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid "Problem urlname:"
msgstr "urlname del problema:"
msgid ""
"To download a CSV listing student responses to a given problem, visit the "
"Data Download section of the Instructor Dashboard."
msgstr ""
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid ""
@@ -15244,6 +15264,20 @@ msgstr ""
msgid "Generate Proctored Exam Results Report"
msgstr "Generar reporte de resultados para examenes supervisados"
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"To generate a CSV file that lists all student answers to a given problem, "
"enter the location of the problem (from its Staff Debug Info)."
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Problem location: "
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Download a CSV of problem responses"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"For smaller courses, click to list profile information for enrolled students"
@@ -17851,67 +17885,51 @@ msgid "This module is not enabled."
msgstr "Este módulo no está habilitado."
#: cms/templates/certificates.html
msgid ""
"Upon successful completion of your course, learners receive a certificate to"
" acknowledge their accomplishment. If you are a course team member with the "
"Admin role in Studio, you can configure your course certificate."
msgid "Working with Certificates"
msgstr ""
"Al completar con éxito el curso, los alumnos reciben un certificado para "
"reconocer su logro. Si usted es un miembro del equipo de curso con el rol de"
" administrador en Studio, puede configurar los certificados del curso."
#: cms/templates/certificates.html
msgid ""
"Click {em_start}Add your first certificate{em_end} to add a certificate "
"configuration. Upload the organization logo to be used on the certificate, "
"and specify at least one signatory. You can include up to four signatories "
"for a certificate. You can also upload a signature image file for each "
"signatory. {em_start}Note:{em_end} Signature images are used only for "
"verified certificates. Optionally, specify a different course title to use "
"on your course certificate. You might want to use a different title if, for "
"example, the official course name is too long to display well on a "
"certificate."
"Specify a course title to use on the certificate if the course's official "
"title is too long to be displayed well."
msgstr ""
"Haga clic en {em_start}Agregar su primer certificado{em_end} para agregar "
"una configuración de certificados. Cargue el logotipo de la organización "
"para ser utilizado en el certificado, y especifique al menos un signatario. "
"Puede incluir hasta cuatro firmantes de un certificado. También puede cargar"
" un archivo de imagen de la firma de cada signatario. "
"{em_start}Nota:{em_end} Las imágenes de la firma sólo se utilizan para los "
"certificados verificados. Opcionalmente, especifique un título de curso "
"diferente a utilizar en su certificado. Es posible que desee utilizar un "
"título diferente si, por ejemplo, el nombre oficial del curso es demasiado "
"largo para que aparezca completo en el certificado."
#: cms/templates/certificates.html
msgid ""
"Select a course mode and click {em_start}Preview Certificate{em_end} to "
"preview the certificate that a learner in the selected enrollment track "
"would receive. When the certificate is ready for issuing, click "
"{em_start}Activate.{em_end} To stop issuing an active certificate, click "
"{em_start}Deactivate{em_end}."
"For verified certificates, specify between one and four signatories and "
"upload the associated images."
msgstr ""
"Seleccione un modo de curso y haga clic en {em_start}Vista previa de "
"Certificado{em_end} para previsualizar el certificado que un estudiante en "
"el modo de curso seleccionado recibiría. Cuando el certificado esté listo "
"para la expedición, haga clic {em_start}Activar{em_end}. Para detener la "
"emisión de un certificado activo, haga clic en {em_start}Desactivar{em_end}."
#: cms/templates/certificates.html
msgid ""
" To edit the certificate configuration, hover over the top right corner of "
"the form and click {em_start}Edit{em_end}. To delete a certificate, hover "
"over the top right corner of the form and click the delete icon. In general,"
" do not delete certificates after a course has started, because some "
"certificates might already have been issued to learners."
"To edit or delete a certificate before it is activated, hover over the top "
"right corner of the form and select {em_start}Edit{em_end} or the delete "
"icon."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"To view a sample certificate, choose a course mode and select "
"{em_start}Preview Certificate{em_end}."
msgstr ""
#: cms/templates/certificates.html
msgid "Issuing Certificates to Learners"
msgstr ""
#: cms/templates/certificates.html
msgid ""
"To begin issuing certificates, a course team member with the Admin role "
"selects {em_start}Activate{em_end}. Course team members without the Admin "
"role cannot edit or delete an activated certificate."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"{em_start}Do not{em_end} delete certificates after a course has started; "
"learners who have already earned certificates will no longer be able to "
"access them."
msgstr ""
"Para editar la configuración del certificado, pase el puntero sobre la "
"esquina superior derecha del formulario y haga clic en "
"{em_start}Editar{em_end}. Para eliminar un certificado, pase el puntero "
"sobre la esquina superior derecha del formulario y haga clic en el icono de "
"eliminación. En general, no elimine los certificados después de que un curso"
" haya iniciado, debido a que algunos certificados pueden ya haber sido "
"emitidos a los alumnos."
#: cms/templates/certificates.html
msgid "Learn more about certificates"

View File

@@ -25,6 +25,7 @@
# Lalo Cabrera <laloogcabrera@yahoo.com.mx>, 2014
# Luis Ricardo Ruiz <luislicardo1307@gmail.com>, 2013
# Luis Ricardo Ruiz <luislicardo1307@gmail.com>, 2013
# Mecabotware <mecabotware.ideas@gmail.com>, 2015
# Natalia, 2013
# Natalia, 2013-2014
# Nuri Plans Toral <nplans@gmail.com>, 2015
@@ -63,6 +64,7 @@
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
# Claudio Anibal Barahona Flores <claudio.barahona@unah.edu.hn>, 2015
# Cristian Salamea <ovnicraft@gmail.com>, 2014-2015
# Giancarlo De Agostini <giancarlo.deagostini@iaen.edu.ec>, 2015
# Jonathan Amaya <jonathan.amaya88@yahoo.com>, 2014
@@ -70,6 +72,7 @@
# Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2014
# Juan Fernando Villa <elite.linux@gmail.com>, 2015
# Juan <juan.marrero@utec.edu.uy>, 2015
# Mecabotware <mecabotware.ideas@gmail.com>, 2015
# Nuri Plans Toral <nplans@gmail.com>, 2014
# Patricia Colmenares <patrusca38@hotmail.com>, 2015
# paul ochoa <palichis@solid-ec.org>, 2015
@@ -89,14 +92,15 @@
# Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2014
# Juan <juan.marrero@utec.edu.uy>, 2015
# karlman72 <karlman72@gmail.com>, 2014
# Leandro Bohnhoff <leandro.bohnhoff@gmail.com>, 2015
# Patricia Colmenares <patrusca38@hotmail.com>, 2015
# UAbierta Universidad de Chile <uabierta@u.uchile.cl>, 2015
msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-21 14:17+0000\n"
"PO-Revision-Date: 2015-08-21 02:41+0000\n"
"POT-Creation-Date: 2015-09-04 14:06+0000\n"
"PO-Revision-Date: 2015-09-04 14:08+0000\n"
"Last-Translator: Sarina Canelake <sarina@edx.org>\n"
"Language-Team: Spanish (Latin America) (http://www.transifex.com/open-edx/edx-platform/language/es_419/)\n"
"MIME-Version: 1.0\n"
@@ -142,8 +146,8 @@ msgstr "Aceptar"
#: cms/static/js/views/show_textbook.js cms/static/js/views/validation.js
#: cms/static/js/views/modals/base_modal.js
#: cms/static/js/views/modals/course_outline_modals.js
#: cms/static/js/views/utils/view_utils.js
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: common/static/common/js/components/utils/view_utils.js
#: cms/templates/js/add-xblock-component-menu-problem.underscore
#: cms/templates/js/add-xblock-component-menu.underscore
#: cms/templates/js/certificate-editor.underscore
@@ -154,6 +158,11 @@ msgstr "Aceptar"
#: cms/templates/js/group-configuration-editor.underscore
#: cms/templates/js/section-name-edit.underscore
#: cms/templates/js/xblock-string-field-editor.underscore
#: common/static/common/templates/discussion/new-post.underscore
#: common/static/common/templates/discussion/response-comment-edit.underscore
#: common/static/common/templates/discussion/thread-edit.underscore
#: common/static/common/templates/discussion/thread-response-edit.underscore
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
#: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore
msgid "Cancel"
msgstr "Cancelar"
@@ -163,17 +172,6 @@ msgstr "Cancelar"
#: cms/static/js/views/manage_users_and_roles.js
#: cms/static/js/views/show_textbook.js
#: common/static/js/vendor/ova/catch/js/catch.js
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-details.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/course-outline.underscore
#: cms/templates/js/course_grade_policy.underscore
#: cms/templates/js/group-configuration-details.underscore
#: cms/templates/js/group-configuration-editor.underscore
#: cms/templates/js/show-textbook.underscore
#: cms/templates/js/signatory-editor.underscore
#: cms/templates/js/xblock-outline.underscore
msgid "Delete"
msgstr "Borrar"
@@ -248,12 +246,10 @@ msgstr "Error"
msgid "Save"
msgstr "Guardar"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: cms/static/js/views/modals/edit_xblock.js
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/signatory-editor.underscore
msgid "Close"
msgstr "Cerrar"
@@ -346,6 +342,8 @@ msgstr ""
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
#: lms/static/coffee/src/staff_grading/staff_grading.js
#: common/static/common/templates/discussion/thread-response.underscore
#: common/static/common/templates/discussion/thread.underscore
#: lms/templates/verify_student/incourse_reverify.underscore
msgid "Submit"
msgstr "Enviar"
@@ -780,18 +778,10 @@ msgstr "Propiedades del documento"
msgid "Edit HTML"
msgstr "Editar HTML"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: common/static/js/vendor/ova/catch/js/catch.js
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/content-group-details.underscore
#: cms/templates/js/course_info_handouts.underscore
#: cms/templates/js/group-configuration-details.underscore
#: cms/templates/js/show-textbook.underscore
#: cms/templates/js/signatory-details.underscore
#: cms/templates/js/xblock-string-field-editor.underscore
msgid "Edit"
msgstr "Editar"
@@ -1192,11 +1182,9 @@ msgstr "Documento nuevo"
msgid "New window"
msgstr "Nueva ventana"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/paging-header.underscore
msgid "Next"
msgstr "Siguiente"
@@ -1546,12 +1534,9 @@ msgstr ""
"La URL que introdujo parece ser un vínculo externo. ¿Desea agregarle el "
"prefijo requerido http://?"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/signatory-details.underscore
#: cms/templates/js/signatory-editor.underscore
msgid "Title"
msgstr "Título"
@@ -2163,6 +2148,18 @@ msgstr ""
msgid "Are you sure you want to delete this response?"
msgstr "¿Está seguro de que desea borrar esta respuesta?"
#: common/static/common/js/components/utils/view_utils.js
msgid "Required field."
msgstr ""
#: common/static/common/js/components/utils/view_utils.js
msgid "Please do not use any spaces in this field."
msgstr ""
#: common/static/common/js/components/utils/view_utils.js
msgid "Please do not use any spaces or special characters in this field."
msgstr ""
#: common/static/common/js/components/views/paging_header.js
msgid "Showing %(first_index)s out of %(num_items)s total"
msgstr "Mostrando %(first_index)s de un total de %(num_items)s "
@@ -2329,6 +2326,7 @@ msgstr "Fecha de publicación"
#: common/static/js/vendor/ova/catch/js/catch.js
#: lms/static/js/courseware/credit_progress.js
#: common/static/common/templates/discussion/forum-actions.underscore
#: lms/templates/discovery/facet.underscore
#: lms/templates/edxnotes/note-item.underscore
msgid "More"
@@ -2408,21 +2406,34 @@ msgid "An unexpected error occurred. Please try again."
msgstr "Se produjo un error inesperado. Por favor, inténtelo nuevamente."
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "last activity"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "open slots"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
#: lms/templates/edxnotes/tab-item.underscore
msgid "name"
msgstr "nombre"
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "open_slots"
msgstr "open_slots"
#. Translators: This refers to the number of teams (a count of how many teams
#. there are)
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
msgid "team count"
msgstr "Cantidad de equipos"
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/group-configuration-editor.underscore
msgid "Create"
msgstr "Crear"
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
msgid "Update"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
msgid "Team Name (Required) *"
msgstr "Nombre del equipo (Requerido) *"
@@ -2491,20 +2502,48 @@ msgstr "La descripción no puede tener más de 300 caracteres."
msgid "You are not currently a member of any team."
msgstr "Usted no es actualmente miembro de ningún equipo."
#. Translators: "and others" refers to fact that additional members of a team
#. exist that are not displayed.
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "and others"
msgstr ""
#. Translators: 'date' is a placeholder for a fuzzy, relative timestamp (see:
#. https://github.com/rmm5t/jquery-timeago)
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "Last Activity %(date)s"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "View %(span_start)s %(team_name)s %(span_end)s"
msgstr "Ver %(span_start)s %(team_name)s %(span_end)s"
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "An error occurred. Try again."
msgstr "Ocurrió un error. Intente nuevamente."
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
msgid "Leave this team?"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
msgid ""
"If you leave, you can no longer post in this team's discussions. Your place "
"will be available to another learner."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
#: lms/static/js/verify_student/views/reverify_view.js
#: lms/templates/verify_student/review_photos_step.underscore
msgid "Confirm"
msgstr "Confirmar"
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "You already belong to another team."
msgstr "Usted ya pertenece a otro equipo."
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "This team is full."
msgstr "Este equipo está lleno."
@@ -2522,6 +2561,10 @@ msgstr "Todos los equipos"
msgid "teams"
msgstr "equipos"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Teams"
msgstr "Equipos"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"See all teams in your course, organized by topic. Join a team to collaborate"
@@ -2530,33 +2573,52 @@ msgstr ""
"Revise los equipos de su curso, organizados por tema. Únase a un equipo para"
" colaborar con otros que estén interesados en los mismos temas."
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Teams"
msgstr "Equipos"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "My Team"
msgstr "Mi equipo"
#. Translators: sr_start and sr_end surround text meant only for screen
#. readers. The whole string will be shown to users as "Browse teams" if they
#. are using a screenreader, and "Browse" otherwise.
#. readers.
#. The whole string will be shown to users as "Browse teams" if they are using
#. a
#. screenreader, and "Browse" otherwise.
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Browse %(sr_start)s teams %(sr_end)s"
msgstr "Explorar %(sr_start)s equpos %(sr_end)s"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Create a new team if you can't find existing teams to join, or if you would "
"like to learn with friends you know."
msgid "Team Search"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Showing results for \"%(searchString)s\""
msgstr ""
"Cree un nuevo equipo si no puede encontrar uno existente para unirse o si "
"desea aprender con personas que ya conoce."
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Create a New Team"
msgstr "Crear un nuevo equipo"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Create a new team if you can't find an existing team to join, or if you "
"would like to learn with friends you know."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
#: lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
msgid "Edit Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"If you make significant changes, make sure you notify members of the team "
"before making these changes."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Search teams"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "All Topics"
msgstr "Todos los temas"
@@ -2579,21 +2641,29 @@ msgid_plural "%(team_count)s Teams"
msgstr[0] "%(team_count)s Equipo"
msgstr[1] "%(team_count)s Equipos"
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "Topic"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "View Teams in the %(topic_name)s Topic"
msgstr "Ver equipos en el tema %(topic_name)s"
#. Translators: this string is shown at the bottom of the teams page
#. to find a team to join or else to create a new one. There are three
#. links that need to be included in the message:
#. 1. Browse teams in other topics
#. 2. search teams
#. 3. create a new team
#. Be careful to start each link with the appropriate start indicator
#. (e.g. {browse_span_start} for #1) and finish it with {span_end}.
#: lms/djangoapps/teams/static/teams/js/views/topic_teams.js
msgid ""
"Try {browse_span_start}browsing all teams{span_end} or "
"{search_span_start}searching team descriptions{span_end}. If you still can't"
" find a team to join, {create_span_start}create a new team in this "
"{browse_span_start}Browse teams in other topics{span_end} or "
"{search_span_start}search teams{span_end} in this topic. If you still can't "
"find a team to join, {create_span_start}create a new team in this "
"topic{span_end}."
msgstr ""
"Intente {browse_span_start}explorar todos los equipos{span_end} o "
"{search_span_start}buscar descripciones de equipos{span_end}. Sí aún no "
"puede encontrar un equipo para unirse, {create_span_start}cree un nuevo "
"equipo en este tema{span_end}."
#: lms/djangoapps/teams/static/teams/js/views/topics.js
msgid "All topics"
@@ -4082,11 +4152,6 @@ msgstr "Tome una foto de su ID"
msgid "Review your info"
msgstr "Revise su información"
#: lms/static/js/verify_student/views/reverify_view.js
#: lms/templates/verify_student/review_photos_step.underscore
msgid "Confirm"
msgstr "Confirmar"
#: lms/static/js/verify_student/views/step_view.js
msgid "An error has occurred. Please try reloading the page."
msgstr "Ocurrió un error. Por favor, intente recargar la página."
@@ -4680,7 +4745,7 @@ msgstr "Su archivo ha sido borrado."
msgid "Date Added"
msgstr "Fecha añadida"
#: cms/static/js/views/assets.js cms/templates/js/asset-library.underscore
#: cms/static/js/views/assets.js
msgid "Type"
msgstr "Escribir"
@@ -5291,19 +5356,6 @@ msgstr ""
"La longitud combinada de los campos para la organización y código de la "
"librería no puede superar los <%=limit%> caracteres."
#: cms/static/js/views/utils/view_utils.js
msgid "Required field."
msgstr "Campo requerido."
#: cms/static/js/views/utils/view_utils.js
msgid "Please do not use any spaces in this field."
msgstr "Por favor, no usar espacios o caracteres especiales en este campo."
#: cms/static/js/views/utils/view_utils.js
msgid "Please do not use any spaces or special characters in this field."
msgstr ""
"Por favor, no utilizar espacios o caracteres especiales en este campo."
#: cms/static/js/views/utils/xblock_utils.js
msgid "component"
msgstr "componente"
@@ -5396,11 +5448,526 @@ msgstr "Acciones"
msgid "Due Date"
msgstr "Fecha límite de entrega"
#: cms/templates/js/paging-header.underscore
#: common/static/common/templates/components/paging-footer.underscore
#: common/static/common/templates/discussion/pagination.underscore
msgid "Previous"
msgstr ""
#: cms/templates/js/previous-video-upload-list.underscore
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
#: lms/templates/verify_student/enrollment_confirmation_step.underscore
msgid "Status"
msgstr "Estado"
#: common/static/common/templates/image-modal.underscore
msgid "Large"
msgstr ""
#: common/static/common/templates/image-modal.underscore
msgid "Zoom In"
msgstr ""
#: common/static/common/templates/image-modal.underscore
msgid "Zoom Out"
msgstr ""
#: common/static/common/templates/components/paging-footer.underscore
msgid "Page number"
msgstr ""
#: common/static/common/templates/components/paging-footer.underscore
msgid "Enter the page number you'd like to quickly navigate to."
msgstr ""
#: common/static/common/templates/components/paging-header.underscore
msgid "Sorted by"
msgstr ""
#: common/static/common/templates/components/search-field.underscore
msgid "Clear search"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "DISCUSSION HOME:"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
#: lms/templates/commerce/provider.underscore
#: lms/templates/commerce/receipt.underscore
#: lms/templates/discovery/course_card.underscore
msgid "gettext("
msgstr "gettext("
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Find discussions"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Focus in on specific topics"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Search for specific posts"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Sort by date, vote, or comments"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Engage with posts"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Upvote posts and good responses"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Report Forum Misuse"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Follow posts for updates"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Receive updates"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Toggle Notifications Setting"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid ""
"Check this box to receive an email digest once a day notifying you about "
"new, unread activity from posts you are following."
msgstr ""
#: common/static/common/templates/discussion/forum-action-answer.underscore
msgid "Mark as Answer"
msgstr ""
#: common/static/common/templates/discussion/forum-action-answer.underscore
msgid "Unmark as Answer"
msgstr ""
#: common/static/common/templates/discussion/forum-action-close.underscore
msgid "Open"
msgstr ""
#: common/static/common/templates/discussion/forum-action-endorse.underscore
msgid "Endorse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-endorse.underscore
msgid "Unendorse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-follow.underscore
msgid "Follow"
msgstr ""
#: common/static/common/templates/discussion/forum-action-follow.underscore
msgid "Unfollow"
msgstr ""
#: common/static/common/templates/discussion/forum-action-pin.underscore
msgid "Pin"
msgstr ""
#: common/static/common/templates/discussion/forum-action-pin.underscore
msgid "Unpin"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Report abuse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Report"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Unreport"
msgstr ""
#: common/static/common/templates/discussion/forum-action-vote.underscore
msgid "Vote for this post,"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Visible To:"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "All Groups"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid ""
"Discussion admins, moderators, and TAs can make their posts visible to all "
"students or specify a single cohort."
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Title:"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Add a clear and descriptive title to encourage participation."
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Enter your question or comment"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "follow this post"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "post anonymously"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "post anonymously to classmates"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Add Post"
msgstr ""
#: common/static/common/templates/discussion/post-user-display.underscore
msgid "Community TA"
msgstr ""
#: common/static/common/templates/discussion/profile-thread.underscore
#: common/static/common/templates/discussion/thread.underscore
msgid "This thread is closed."
msgstr ""
#: common/static/common/templates/discussion/profile-thread.underscore
msgid "View discussion"
msgstr ""
#: common/static/common/templates/discussion/response-comment-edit.underscore
msgid "Editing comment"
msgstr ""
#: common/static/common/templates/discussion/response-comment-edit.underscore
msgid "Update comment"
msgstr ""
#: common/static/common/templates/discussion/response-comment-show.underscore
#, python-format
msgid "posted %(time_ago)s by %(author)s"
msgstr ""
#: common/static/common/templates/discussion/response-comment-show.underscore
#: common/static/common/templates/discussion/thread-response-show.underscore
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Reported"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Editing post"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Edit post title"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Update post"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "discussion"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "answered question"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "unanswered question"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Pinned"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "Following"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "By: Staff"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "By: Community TA"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#: common/static/common/templates/discussion/thread-response-show.underscore
msgid "fmt"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#, python-format
msgid ""
"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s "
"unread comments)%(span_close)s"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#, python-format
msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-edit.underscore
msgid "Editing response"
msgstr ""
#: common/static/common/templates/discussion/thread-response-edit.underscore
msgid "Update response"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "marked as answer %(time_ago)s by %(user)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "marked as answer %(time_ago)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "endorsed %(time_ago)s by %(user)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "endorsed %(time_ago)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response.underscore
msgid "fmts"
msgstr ""
#: common/static/common/templates/discussion/thread-response.underscore
msgid "Add a comment"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "This post is visible only to %(group_name)s."
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
msgid "This post is visible to everyone."
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "%(post_type)s posted %(time_ago)s by %(author)s"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Closed"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "Related to: %(courseware_title_linked)s"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Post type:"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Question"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Discussion"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid ""
"Questions raise issues that need answers. Discussions share ideas and start "
"conversations."
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Add a Response"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Post a response:"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Expand discussion"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Collapse discussion"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Topic Area:"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Discussion topics; current selection is:"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Filter topics"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Add your post to a relevant topic to help others find it."
msgstr ""
#: common/static/common/templates/discussion/user-profile.underscore
msgid "Active Threads"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates.underscore
msgid "username or email"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "No results"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Course Key"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Download URL"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Grade"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Last Updated"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Download the user's certificate"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Not available"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Regenerate"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Regenerate the user's certificate"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Your team could not be created."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Your team could not be updated."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid ""
"Enter information to describe your team. You cannot change these details "
"after you create the team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Optional Characteristics"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid ""
"Help other learners decide whether to join your team by specifying some "
"characteristics for your team. Choose carefully, because fewer people might "
"be interested in joining your team if it seems too restrictive."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Create team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Update team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel team creating."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel team updating."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-actions.underscore
msgid "Are you having trouble finding a team to join?"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
msgid "Join Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "New Post"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team Details"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "You are a member of this team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team member profiles"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team capacity"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "country"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "language"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Leave Team"
msgstr ""
#: lms/static/js/fixtures/donation.underscore
#: lms/templates/dashboard/donation.underscore
msgid "Donate"
msgstr "Donar"
#: lms/templates/ccx/schedule.underscore
msgid "Expand All"
msgstr "Expandir todo"
@@ -5441,12 +6008,6 @@ msgstr "Mover Subsección"
msgid "Subsection"
msgstr "Subsección"
#: lms/templates/commerce/provider.underscore
#: lms/templates/commerce/receipt.underscore
#: lms/templates/discovery/course_card.underscore
msgid "gettext("
msgstr "gettext("
#: lms/templates/commerce/provider.underscore
#, python-format
msgid "<img src='%s' alt='%s'></image>"
@@ -5543,10 +6104,6 @@ msgstr "Marcar el examen como completado"
msgid "End My Exam"
msgstr "Terminar mi examen"
#: lms/templates/dashboard/donation.underscore
msgid "Donate"
msgstr "Donar"
#: lms/templates/discovery/course_card.underscore
msgid "LEARN MORE"
msgstr "APRENDER MAS"
@@ -6572,6 +7129,16 @@ msgstr "Arrastre y suelte o pulse aquí para subir ficheros de vídeo."
msgid "status"
msgstr "estado"
#: cms/templates/js/add-xblock-component-button.underscore
msgid "Add Component:"
msgstr ""
#: cms/templates/js/add-xblock-component-menu-problem.underscore
#: cms/templates/js/add-xblock-component-menu.underscore
#, python-format
msgid "%(type)s Component Template Menu"
msgstr ""
#: cms/templates/js/add-xblock-component-menu-problem.underscore
msgid "Common Problem Types"
msgstr "Tipos de problemas comunes"
@@ -6646,6 +7213,11 @@ msgstr "ID"
msgid "Certificate Details"
msgstr "Detalles del certificado"
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
msgid "Course Title"
msgstr ""
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
msgid "Course Title Override"
@@ -6692,19 +7264,13 @@ msgstr ""
" en los certificados. Dejar vacío para utilizar el título oficial del curso."
#: cms/templates/js/certificate-editor.underscore
msgid "Add Signatory"
msgstr "Añadir signatario"
msgid "Add Additional Signatory"
msgstr ""
#: cms/templates/js/certificate-editor.underscore
msgid "(Up to 4 signatories are allowed for a certificate)"
msgstr "(Se permiten hasta 4 signatarios por certificado)"
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/group-configuration-editor.underscore
msgid "Create"
msgstr "Crear"
#: cms/templates/js/certificate-web-preview.underscore
msgid "Choose mode"
msgstr "Elegir modo"
@@ -7142,10 +7708,6 @@ msgstr "No ha añadido aún ningún libro de texto a este curso."
msgid "Add your first textbook"
msgstr "Añada su primer libro de texto"
#: cms/templates/js/paging-header.underscore
msgid "Previous"
msgstr "Anterior"
#: cms/templates/js/previous-video-upload-list.underscore
msgid "Previous Uploads"
msgstr "Subidas anteriores"

Binary file not shown.

View File

@@ -178,7 +178,7 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-21 14:18+0000\n"
"POT-Creation-Date: 2015-09-04 14:07+0000\n"
"PO-Revision-Date: 2015-06-19 17:16+0000\n"
"Last-Translator: Xavier Antoviaque <xavier@antoviaque.org>\n"
"Language-Team: French (http://www.transifex.com/open-edx/edx-platform/language/fr/)\n"
@@ -340,6 +340,7 @@ msgstr "Cours"
msgid "Display Name"
msgstr "Nom d'affichage"
#: common/djangoapps/course_modes/models.py
#: lms/templates/courseware/course_about.html
msgid "Price"
msgstr "Prix"
@@ -471,7 +472,7 @@ msgstr "Message à afficher lorsque l'utilisateur est bloqué a l'inscription."
#: common/djangoapps/embargo/models.py
msgid "The message to show when a user is blocked from accessing a course."
msgstr ""
msgstr "Message à afficher lorsqu'un utilisateur a un accès au cours bloqué."
#: common/djangoapps/embargo/models.py
msgid ""
@@ -635,7 +636,7 @@ msgstr "Diplôme de premier cycle supérieur"
#: common/djangoapps/student/models.py
msgid "Associate degree"
msgstr ""
msgstr "Niveau associé"
#: common/djangoapps/student/models.py
msgid "Secondary/high school"
@@ -658,15 +659,15 @@ msgstr "Aucun"
#: common/djangoapps/student/models.py
msgid "{platform_name} Honor Code Certificate for {course_name}"
msgstr ""
msgstr "{platform_name} Certificat sur l'honneur pour {course_name}"
#: common/djangoapps/student/models.py
msgid "{platform_name} Verified Certificate for {course_name}"
msgstr ""
msgstr "{platform_name} Certificat Vérifié pour {course_name}"
#: common/djangoapps/student/models.py
msgid "{platform_name} Professional Certificate for {course_name}"
msgstr ""
msgstr "{platform_name} Certificat professionnel {course_name}"
#: common/djangoapps/student/models.py
msgid ""
@@ -683,7 +684,7 @@ msgstr ""
#: common/djangoapps/student/models.py
msgid "{platform_name} Certificate for {course_name}"
msgstr ""
msgstr "{platform_name} Certificat pour {course_name}"
#: common/djangoapps/student/models.py
msgid "The ISO 639-1 language code for this language."
@@ -1371,10 +1372,6 @@ msgstr "correct"
msgid "incorrect"
msgstr "incorrect"
#: common/lib/capa/capa/inputtypes.py
msgid "partially correct"
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "incomplete"
msgstr "incomplet"
@@ -1397,10 +1394,6 @@ msgstr "Ceci est correct."
msgid "This is incorrect."
msgstr "Ceci est incorrect."
#: common/lib/capa/capa/inputtypes.py
msgid "This is partially correct."
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "This is unanswered."
msgstr ""
@@ -1455,7 +1448,7 @@ msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "Error running code."
msgstr ""
msgstr "Erreur lors de l'exécution du code."
#: common/lib/capa/capa/inputtypes.py
msgid "Cannot connect to the queue"
@@ -2325,11 +2318,11 @@ msgstr ""
#: common/lib/xmodule/xmodule/course_module.py
msgid "Date that enrollment for this class is opened"
msgstr ""
msgstr "Date de début des inscriptions pour ce cours"
#: common/lib/xmodule/xmodule/course_module.py
msgid "Date that enrollment for this class is closed"
msgstr ""
msgstr "Date de fin des inscriptions pour ce cours"
#: common/lib/xmodule/xmodule/course_module.py
msgid "Start time when this module is visible"
@@ -2337,7 +2330,7 @@ msgstr ""
#: common/lib/xmodule/xmodule/course_module.py
msgid "Date that this class ends"
msgstr ""
msgstr "Date à laquelle se termine ce cours"
#: common/lib/xmodule/xmodule/course_module.py
msgid "Cosmetic Course Display Price"
@@ -3148,7 +3141,7 @@ msgstr "Inscriptions sur invitation par l'équipe pédagogique uniquement."
#: common/lib/xmodule/xmodule/course_module.py
msgid "Pre-Course Survey Name"
msgstr "Nom de lEnquête d'Avant Cours "
msgstr "Nom de lenquête d'avant cours "
#: common/lib/xmodule/xmodule/course_module.py
msgid "Name of SurveyForm to display as a pre-course survey to the user."
@@ -3158,7 +3151,7 @@ msgstr ""
#: common/lib/xmodule/xmodule/course_module.py
msgid "Pre-Course Survey Required"
msgstr "Enquête d'Avant Cours Requise"
msgstr "Enquête d'avant cours requise"
#: common/lib/xmodule/xmodule/course_module.py
msgid ""
@@ -3574,11 +3567,11 @@ msgstr ""
#: common/lib/xmodule/xmodule/library_content_module.py
msgid "Invalid Library"
msgstr ""
msgstr "Bibliothèque invalide"
#: common/lib/xmodule/xmodule/library_content_module.py
msgid "No Library Selected"
msgstr ""
msgstr "Aucune bibliothèque sélectionnée"
#: common/lib/xmodule/xmodule/library_root_xblock.py
msgid "Enter the name of the library as it should appear in Studio."
@@ -3708,7 +3701,7 @@ msgstr ""
#: common/lib/xmodule/xmodule/lti_module.py
msgid "Request user's username"
msgstr ""
msgstr "Demander le nom de l'utilisateur"
#: common/lib/xmodule/xmodule/lti_module.py
msgid ""
@@ -5088,7 +5081,14 @@ msgid "{month} {day}, {year}"
msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid "a course of study offered by {partner_name}, through {platform_name}."
msgid ""
"a course of study offered by {partner_short_name}, an online learning "
"initiative of {partner_long_name} through {platform_name}."
msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"a course of study offered by {partner_short_name}, through {platform_name}."
msgstr ""
#. Translators: Accomplishments describe the awards/certifications obtained by
@@ -5188,13 +5188,13 @@ msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"This is a valid {platform_name} certificate for {user_name}, who "
"participated in {partner_name} {course_number}"
"participated in {partner_short_name} {course_number}"
msgstr ""
#. Translators: This text is bound to the HTML 'title' element of the page
#. and appears in the browser title bar
#: lms/djangoapps/certificates/views/webview.py
msgid "{partner_name} {course_number} Certificate | {platform_name}"
msgid "{partner_short_name} {course_number} Certificate | {platform_name}"
msgstr ""
#. Translators: This text fragment appears after the student's name
@@ -5351,6 +5351,14 @@ msgid ""
"{payment_support_link}."
msgstr ""
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "{course_id} is not a valid course key."
msgstr ""
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "Course {course_id} does not exist."
msgstr ""
#: lms/djangoapps/course_wiki/tab.py lms/djangoapps/course_wiki/views.py
#: lms/templates/wiki/base.html
msgid "Wiki"
@@ -5897,6 +5905,23 @@ msgstr ""
msgid "File is not attached."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid "Could not find problem with this location."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"The problem responses report is being created. To view the status of the "
"report, see Pending Tasks below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A problem responses report generation task is already in progress. Check the"
" 'Pending Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid "Invoice number '{num}' does not exist."
msgstr ""
@@ -6296,6 +6321,10 @@ msgstr "CourseMode en mode ralenti ({mode_slug}) n'existe pas"
msgid "CourseMode price updated successfully"
msgstr "Le prix du CourseMode a été correctement mis à jour"
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "No end date set"
msgstr ""
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "Enrollment data is now available in {dashboard_link}."
msgstr ""
@@ -6393,18 +6422,6 @@ msgstr "Email externe"
msgid "Grades for assignment \"{name}\""
msgstr "Notes pour le travail \"{name}\""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Found {num} records to dump."
msgstr " A trouvé {num} enregistrements à jeter."
#: lms/djangoapps/instructor/views/legacy.py
msgid "Couldn't find module with that urlname."
msgstr "Impossible de trouver un module avec cette URL."
#: lms/djangoapps/instructor/views/legacy.py
msgid "Student state for problem {problem}"
msgstr "Etat de létudiant pour le problème {problem}"
#: lms/djangoapps/instructor/views/legacy.py
msgid "Grades from {course_id}"
msgstr "Notes de {course_id}"
@@ -6579,6 +6596,12 @@ msgstr "supprimé"
msgid "emailed"
msgstr "envoyé par e-mail"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr ""
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -6591,12 +6614,6 @@ msgstr "noté"
msgid "problem distribution graded"
msgstr ""
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr ""
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -8118,11 +8135,11 @@ msgid "course_id must be provided"
msgstr ""
#: lms/djangoapps/teams/views.py
msgid "The supplied topic id {topic_id} is not valid"
msgid "text_search and order_by cannot be provided together"
msgstr ""
#: lms/djangoapps/teams/views.py
msgid "text_search is not yet supported."
msgid "The supplied topic id {topic_id} is not valid"
msgstr ""
#. Translators: 'ordering' is a string describing a way
@@ -9805,7 +9822,7 @@ msgstr "Numéro du cours"
#: cms/templates/course_outline.html
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid "Course Start Date:"
msgstr ""
msgstr "Date de début du cours :"
#: cms/templates/html_error.html lms/templates/module-error.html
msgid "Error:"
@@ -9916,7 +9933,7 @@ msgstr "Menu du cours"
#: cms/templates/widgets/header.html lms/templates/navigation-edx.html
#: lms/templates/navigation.html
msgid "Account"
msgstr ""
msgstr "Compte"
#: cms/templates/widgets/header.html lms/templates/help_modal.html
#: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py
@@ -9928,6 +9945,10 @@ msgstr "Aide"
msgid "Sign Out"
msgstr "Se déconnecter"
#: common/lib/capa/capa/templates/codeinput.html
msgid "{programming_language} editor"
msgstr ""
#: common/templates/license.html
msgid "All Rights Reserved"
msgstr "Tous droits réservés"
@@ -12570,8 +12591,10 @@ msgid "Section:"
msgstr "Section :"
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid "Problem urlname:"
msgstr "url de l'exercice :"
msgid ""
"To download a CSV listing student responses to a given problem, visit the "
"Data Download section of the Instructor Dashboard."
msgstr ""
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid ""
@@ -14379,7 +14402,7 @@ msgstr "Information d'inscription"
#. 'audit')
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid "Number of enrollees (admins, staff, and students) by track"
msgstr ""
msgstr "Nombre d'inscrits (admins, staff, and students) par mode"
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid "Audit"
@@ -14403,7 +14426,7 @@ msgstr "Nom d'affichage du cours :"
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid "Course End Date:"
msgstr ""
msgstr "Date de fin du cours"
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid "Has the course started?"
@@ -14423,7 +14446,7 @@ msgstr "Le cours est-il terminé ?"
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid "Number of sections:"
msgstr ""
msgstr "Nombre de sections:"
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid "Grade Cutoffs:"
@@ -14480,6 +14503,11 @@ msgid ""
"background, meaning it is OK to navigate away from this page while your "
"report is generating."
msgstr ""
"Pour les cours à grande échelle, la création des rapports peut prendre "
"plusieurs heures. Quand la création du rapport est achevée, un lien incluant"
" la date et l'heure de la création est affiché dans le tableau ci-dessous. "
"Ces rapports sont créés en tâche de fond, cela signifie qu'il est possible "
"de naviguer dans d'autres pages en parallèle de la création des rapports."
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
@@ -14519,6 +14547,20 @@ msgstr ""
msgid "Generate Proctored Exam Results Report"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"To generate a CSV file that lists all student answers to a given problem, "
"enter the location of the problem (from its Staff Debug Info)."
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Problem location: "
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Download a CSV of problem responses"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"For smaller courses, click to list profile information for enrolled students"
@@ -15218,13 +15260,15 @@ msgstr "Importer CSV"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Batch Beta Tester Addition"
msgstr "Ajout par des bêta testeurs par lots"
msgstr "Ajout de bêta testeurs"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Note: Users must have an activated {platform_name} account before they can "
"be enrolled as beta testers."
msgstr ""
"Note: Les utilisateurs doivent avoir activé leur compte {platform_name} "
"avant de pouvoir être ajouté en bêta testeur."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
@@ -15252,14 +15296,14 @@ msgstr "Supprimer des bêta-testeurs"
#. users can be added to.
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Course Team Management"
msgstr ""
msgstr "Gestion de l'équipe du cours"
#. Translators: an "Administrator Group" is a group, such as Course Staff,
#. that
#. users can be added to.
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Select a course team role:"
msgstr ""
msgstr "Sélectionner un rôle:"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Getting available lists..."
@@ -15279,10 +15323,16 @@ msgid ""
"all course data. Staff also have access to your course in Studio and "
"Insights. You can only give course team roles to enrolled users."
msgstr ""
"Les membres de l'équipe avec le rôle Équipe pédagogique aident à la gestion "
"du cours. L'équipe pédagogique peut inscrire et désinscrire des "
"participants, ainsi que modifier les notes aux exercices et accéder à "
"l'ensemble des données du cours. L'équipe pédagogique a également accès au "
"cours dans Studio. Vous ne pouvez affecter des rôles que pour les "
"utilisateurs inscrits au cours."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Staff"
msgstr "Ajouter à léquipe"
msgstr "Ajouter à Équipe pédagogique"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
@@ -15292,10 +15342,15 @@ msgid ""
" to manage course team membership. You can only give course team roles to "
"enrolled users."
msgstr ""
"Les membres de l'équipe avec le rôle Admin aident à la gestion du cours. Ils"
" peuvent également effectuer toutes les actions comme l'Équipe pédagogique, "
"mais aussi ajouter ou supprimer des membres Admin, gérer les rôles de "
"modérations des forums, l'ajout de bêta-testeurs. Vous ne pouvez affecter "
"des rôles que pour les utilisateurs inscrits au cours."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Admin"
msgstr ""
msgstr "Ajouter un Admin"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Beta Testers"
@@ -15307,6 +15362,10 @@ msgid ""
"sure that the content works, but have no additional privileges. You can only"
" give course team roles to enrolled users."
msgstr ""
"Les Bêta-testeurs peuvent voir le contenu du cours avant les autres "
"participants. Ils peuvent ainsi s'assurer que le contenu fonctionne, mais ne"
" disposent pas de permissions supplémentaires. Vous ne pouvez affecter de "
"rôle uniquement à des utilisateurs inscrits."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Beta Tester"
@@ -15324,6 +15383,12 @@ msgid ""
"moderation roles to manage course team membership. You can only give course "
"team roles to enrolled users."
msgstr ""
"Les Administrateurs de discussions peuvent modifier et supprimer tous les "
"post, les dénonciations abusives, fermer et réouvrir des sujets, indiquer "
"des réponses et voir les posts de toutes les cohortes. Leur posts sont "
"marqués comme 'Équipe pédagogique'. Ils peuvent aussi modifier les rôles de "
"modérations des utilisateurs. Vous pouvez donner un rôle d'équipe uniquement"
" à des utilisateurs inscrits au cours."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Discussion Admin"
@@ -15341,6 +15406,12 @@ msgid ""
" by adding or removing discussion moderation roles. You can only give course"
" team roles to enrolled users."
msgstr ""
"Les Modérateurs de discussions peuvent modifier et supprimer tous les post, "
"les dénonciations abusives, fermer et réouvrir des sujets, indiquer des "
"réponses et voir les posts de toutes les cohortes. Leur posts sont marqués "
"comme 'Équipe pédagogique'. Ils ne peuvent pas modifier les rôles de "
"modérations des utilisateurs. Vous pouvez donner un rôle d'équipe uniquement"
" à des utilisateurs inscrits au cours."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Moderator"
@@ -15358,10 +15429,16 @@ msgid ""
"from all cohorts. Their posts are marked as 'Community TA'. You can only "
"give course team roles to enrolled users."
msgstr ""
"Les Assistants peuvent modifier et supprimer tous les post, les "
"dénonciations abusives, fermer et réouvrir des sujets, indiquer des réponses"
" et voir les posts de toutes les cohortes. Leur posts sont marqués comme "
"'Assistants'. Ils ne peuvent pas modifier les rôles de modérations des "
"utilisateurs. Vous pouvez donner un rôle d'équipe uniquement à des "
"utilisateurs inscrits au cours."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Community TA"
msgstr "Ajouter un Community TA"
msgstr "Ajouter un Assistant"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "CCX Coaches"
@@ -16568,7 +16645,7 @@ msgstr "Se connecter ou s'inscrire"
#: lms/templates/student_profile/learner_profile.html
msgid "Learner Profile"
msgstr ""
msgstr "Profil de participant"
#. Translators: this section lists all the third-party authentication
#. providers
@@ -16614,7 +16691,7 @@ msgstr "Enquête Utilisateur"
#: lms/templates/survey/survey.html
msgid "Pre-Course Survey"
msgstr ""
msgstr "Enquête d'avant-cours "
#: lms/templates/survey/survey.html
msgid ""
@@ -16623,6 +16700,9 @@ msgid ""
" use of {platform_name} only. It will not be linked to your public profile "
"in any way."
msgstr ""
"Vous pourrez démarrer votre cours une fois rempli le formulaire suivant. Les"
" champs obligatoires sont signalés par une astérisque (*). Ces informations "
"sont utilisées uniquement par {platform_name}."
#: lms/templates/survey/survey.html
msgid "You are missing the following required fields:"
@@ -16669,7 +16749,7 @@ msgstr ""
#: lms/templates/verify_student/incourse_reverify.html
msgid "Re-Verify for {course_name}"
msgstr ""
msgstr "Re-Vérification pour {course_name}"
#: lms/templates/verify_student/missed_deadline.html
msgid "Verification Deadline Has Passed"
@@ -16984,41 +17064,50 @@ msgid "This module is not enabled."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"Upon successful completion of your course, learners receive a certificate to"
" acknowledge their accomplishment. If you are a course team member with the "
"Admin role in Studio, you can configure your course certificate."
msgid "Working with Certificates"
msgstr ""
#: cms/templates/certificates.html
msgid ""
"Click {em_start}Add your first certificate{em_end} to add a certificate "
"configuration. Upload the organization logo to be used on the certificate, "
"and specify at least one signatory. You can include up to four signatories "
"for a certificate. You can also upload a signature image file for each "
"signatory. {em_start}Note:{em_end} Signature images are used only for "
"verified certificates. Optionally, specify a different course title to use "
"on your course certificate. You might want to use a different title if, for "
"example, the official course name is too long to display well on a "
"certificate."
"Specify a course title to use on the certificate if the course's official "
"title is too long to be displayed well."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"Select a course mode and click {em_start}Preview Certificate{em_end} to "
"preview the certificate that a learner in the selected enrollment track "
"would receive. When the certificate is ready for issuing, click "
"{em_start}Activate.{em_end} To stop issuing an active certificate, click "
"{em_start}Deactivate{em_end}."
"For verified certificates, specify between one and four signatories and "
"upload the associated images."
msgstr ""
#: cms/templates/certificates.html
msgid ""
" To edit the certificate configuration, hover over the top right corner of "
"the form and click {em_start}Edit{em_end}. To delete a certificate, hover "
"over the top right corner of the form and click the delete icon. In general,"
" do not delete certificates after a course has started, because some "
"certificates might already have been issued to learners."
"To edit or delete a certificate before it is activated, hover over the top "
"right corner of the form and select {em_start}Edit{em_end} or the delete "
"icon."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"To view a sample certificate, choose a course mode and select "
"{em_start}Preview Certificate{em_end}."
msgstr ""
#: cms/templates/certificates.html
msgid "Issuing Certificates to Learners"
msgstr ""
#: cms/templates/certificates.html
msgid ""
"To begin issuing certificates, a course team member with the Admin role "
"selects {em_start}Activate{em_end}. Course team members without the Admin "
"role cannot edit or delete an activated certificate."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"{em_start}Do not{em_end} delete certificates after a course has started; "
"learners who have already earned certificates will no longer be able to "
"access them."
msgstr ""
#: cms/templates/certificates.html
@@ -17494,6 +17583,9 @@ msgid ""
"date. When you configure a subsection, you can also set the grading policy "
"and due date."
msgstr ""
"Sélectionnez l'icône Configuration pour une section ou une sous-section pour"
" définir sa date de publication. Lorsque vous configurez une sous-section, "
"vous pouvez également définir le type de devoir et la date d'échéance."
#: cms/templates/course_outline.html
msgid "Changing the content students see"

View File

@@ -110,8 +110,8 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-21 14:17+0000\n"
"PO-Revision-Date: 2015-08-21 02:41+0000\n"
"POT-Creation-Date: 2015-09-04 14:06+0000\n"
"PO-Revision-Date: 2015-09-04 14:08+0000\n"
"Last-Translator: Sarina Canelake <sarina@edx.org>\n"
"Language-Team: French (http://www.transifex.com/open-edx/edx-platform/language/fr/)\n"
"MIME-Version: 1.0\n"
@@ -157,8 +157,8 @@ msgstr "OK"
#: cms/static/js/views/show_textbook.js cms/static/js/views/validation.js
#: cms/static/js/views/modals/base_modal.js
#: cms/static/js/views/modals/course_outline_modals.js
#: cms/static/js/views/utils/view_utils.js
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: common/static/common/js/components/utils/view_utils.js
#: cms/templates/js/add-xblock-component-menu-problem.underscore
#: cms/templates/js/add-xblock-component-menu.underscore
#: cms/templates/js/certificate-editor.underscore
@@ -169,6 +169,11 @@ msgstr "OK"
#: cms/templates/js/group-configuration-editor.underscore
#: cms/templates/js/section-name-edit.underscore
#: cms/templates/js/xblock-string-field-editor.underscore
#: common/static/common/templates/discussion/new-post.underscore
#: common/static/common/templates/discussion/response-comment-edit.underscore
#: common/static/common/templates/discussion/thread-edit.underscore
#: common/static/common/templates/discussion/thread-response-edit.underscore
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
#: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore
msgid "Cancel"
msgstr "Annuler"
@@ -178,17 +183,6 @@ msgstr "Annuler"
#: cms/static/js/views/manage_users_and_roles.js
#: cms/static/js/views/show_textbook.js
#: common/static/js/vendor/ova/catch/js/catch.js
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-details.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/course-outline.underscore
#: cms/templates/js/course_grade_policy.underscore
#: cms/templates/js/group-configuration-details.underscore
#: cms/templates/js/group-configuration-editor.underscore
#: cms/templates/js/show-textbook.underscore
#: cms/templates/js/signatory-editor.underscore
#: cms/templates/js/xblock-outline.underscore
msgid "Delete"
msgstr "Supprimer"
@@ -263,12 +257,10 @@ msgstr "Erreur"
msgid "Save"
msgstr "Enregistrer"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: cms/static/js/views/modals/edit_xblock.js
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/signatory-editor.underscore
msgid "Close"
msgstr "Fermer"
@@ -358,6 +350,8 @@ msgstr "Votre résultat n'est pas suffisant pour passer à l'étape suivante."
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
#: lms/static/coffee/src/staff_grading/staff_grading.js
#: common/static/common/templates/discussion/thread-response.underscore
#: common/static/common/templates/discussion/thread.underscore
#: lms/templates/verify_student/incourse_reverify.underscore
msgid "Submit"
msgstr "Soumettre"
@@ -790,18 +784,10 @@ msgstr "Propriétés du document"
msgid "Edit HTML"
msgstr "Editer le code HTML"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: common/static/js/vendor/ova/catch/js/catch.js
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/content-group-details.underscore
#: cms/templates/js/course_info_handouts.underscore
#: cms/templates/js/group-configuration-details.underscore
#: cms/templates/js/show-textbook.underscore
#: cms/templates/js/signatory-details.underscore
#: cms/templates/js/xblock-string-field-editor.underscore
msgid "Edit"
msgstr "Éditer"
@@ -1555,12 +1541,9 @@ msgstr ""
"L'URL que vous avez entrée semble être un lien externe. Voulez-vous ajouter "
"le préfixe http:// requis ?"
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/signatory-details.underscore
#: cms/templates/js/signatory-editor.underscore
msgid "Title"
msgstr "Titre"
@@ -2187,6 +2170,18 @@ msgstr ""
msgid "Are you sure you want to delete this response?"
msgstr "Voulez-vous vraiment supprimer cette réponse ?"
#: common/static/common/js/components/utils/view_utils.js
msgid "Required field."
msgstr ""
#: common/static/common/js/components/utils/view_utils.js
msgid "Please do not use any spaces in this field."
msgstr ""
#: common/static/common/js/components/utils/view_utils.js
msgid "Please do not use any spaces or special characters in this field."
msgstr ""
#: common/static/common/js/components/views/paging_header.js
msgid "Showing %(first_index)s out of %(num_items)s total"
msgstr "%(first_index)s sur %(num_items)s au total"
@@ -2352,6 +2347,7 @@ msgstr "Date de l'envoi"
#: common/static/js/vendor/ova/catch/js/catch.js
#: lms/static/js/courseware/credit_progress.js
#: common/static/common/templates/discussion/forum-actions.underscore
#: lms/templates/discovery/facet.underscore
#: lms/templates/edxnotes/note-item.underscore
msgid "More"
@@ -2431,21 +2427,34 @@ msgid "An unexpected error occurred. Please try again."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "last activity"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "open slots"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
#: lms/templates/edxnotes/tab-item.underscore
msgid "name"
msgstr "nom"
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "open_slots"
msgstr ""
#. Translators: This refers to the number of teams (a count of how many teams
#. there are)
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
msgid "team count"
msgstr "total équipe"
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/group-configuration-editor.underscore
msgid "Create"
msgstr "Créer"
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
msgid "Update"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
msgid "Team Name (Required) *"
msgstr ""
@@ -2470,6 +2479,7 @@ msgid "Language"
msgstr "Langue"
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid ""
"The language that team members primarily use to communicate with each other."
msgstr ""
@@ -2480,6 +2490,7 @@ msgid "Country"
msgstr "Pays"
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "The country that team members primarily identify with."
msgstr ""
@@ -2512,20 +2523,48 @@ msgstr ""
msgid "You are not currently a member of any team."
msgstr ""
#. Translators: "and others" refers to fact that additional members of a team
#. exist that are not displayed.
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "and others"
msgstr ""
#. Translators: 'date' is a placeholder for a fuzzy, relative timestamp (see:
#. https://github.com/rmm5t/jquery-timeago)
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "Last Activity %(date)s"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "View %(span_start)s %(team_name)s %(span_end)s"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "An error occurred. Try again."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
msgid "Leave this team?"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
msgid ""
"If you leave, you can no longer post in this team's discussions. Your place "
"will be available to another learner."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
#: lms/static/js/verify_student/views/reverify_view.js
#: lms/templates/verify_student/review_photos_step.underscore
msgid "Confirm"
msgstr "Confirmer"
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "You already belong to another team."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "This team is full."
msgstr ""
@@ -2543,37 +2582,62 @@ msgstr ""
msgid "teams"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Teams"
msgstr "Équipes"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"See all teams in your course, organized by topic. Join a team to collaborate"
" with other learners who are interested in the same topic as you are."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Teams"
msgstr "Équipes"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "My Team"
msgstr ""
#. Translators: sr_start and sr_end surround text meant only for screen
#. readers. The whole string will be shown to users as "Browse teams" if they
#. are using a screenreader, and "Browse" otherwise.
#. readers.
#. The whole string will be shown to users as "Browse teams" if they are using
#. a
#. screenreader, and "Browse" otherwise.
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Browse %(sr_start)s teams %(sr_end)s"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Create a new team if you can't find existing teams to join, or if you would "
"like to learn with friends you know."
msgid "Team Search"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Showing results for \"%(searchString)s\""
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Create a New Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Create a new team if you can't find an existing team to join, or if you "
"would like to learn with friends you know."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
#: lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
msgid "Edit Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"If you make significant changes, make sure you notify members of the team "
"before making these changes."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Search teams"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "All Topics"
msgstr ""
@@ -2596,15 +2660,27 @@ msgid_plural "%(team_count)s Teams"
msgstr[0] "%(team_count)s Equipe"
msgstr[1] "%(team_count)s Équipes"
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "Topic"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "View Teams in the %(topic_name)s Topic"
msgstr "Voir les équipes du sujet %(topic_name)s"
#. Translators: this string is shown at the bottom of the teams page
#. to find a team to join or else to create a new one. There are three
#. links that need to be included in the message:
#. 1. Browse teams in other topics
#. 2. search teams
#. 3. create a new team
#. Be careful to start each link with the appropriate start indicator
#. (e.g. {browse_span_start} for #1) and finish it with {span_end}.
#: lms/djangoapps/teams/static/teams/js/views/topic_teams.js
msgid ""
"Try {browse_span_start}browsing all teams{span_end} or "
"{search_span_start}searching team descriptions{span_end}. If you still can't"
" find a team to join, {create_span_start}create a new team in this "
"{browse_span_start}Browse teams in other topics{span_end} or "
"{search_span_start}search teams{span_end} in this topic. If you still can't "
"find a team to join, {create_span_start}create a new team in this "
"topic{span_end}."
msgstr ""
@@ -4073,11 +4149,6 @@ msgstr "Prenez une photo de votre pièce d'identité"
msgid "Review your info"
msgstr "Vérifiez vos informations"
#: lms/static/js/verify_student/views/reverify_view.js
#: lms/templates/verify_student/review_photos_step.underscore
msgid "Confirm"
msgstr "Confirmer"
#: lms/static/js/verify_student/views/step_view.js
msgid "An error has occurred. Please try reloading the page."
msgstr "Une erreur est survenue. Essayez de rafraîchir la page."
@@ -4591,6 +4662,7 @@ msgstr ""
#: cms/static/js/models/settings/course_details.js
msgid "The course end date must be later than the course start date."
msgstr ""
"La date de fin du cours doit être postérieure à la date de début du cours."
#: cms/static/js/models/settings/course_details.js
msgid "The course start date must be later than the enrollment start date."
@@ -4669,7 +4741,7 @@ msgstr "Votre fichier a été supprimé."
msgid "Date Added"
msgstr "Date ajoutée"
#: cms/static/js/views/assets.js cms/templates/js/asset-library.underscore
#: cms/static/js/views/assets.js
msgid "Type"
msgstr "Type"
@@ -5252,19 +5324,6 @@ msgstr ""
"La longueur totale des champs organisation et codes de bibliothèque ne doit "
"pas dépasser <%=limit%> caractères."
#: cms/static/js/views/utils/view_utils.js
msgid "Required field."
msgstr "Champ requis."
#: cms/static/js/views/utils/view_utils.js
msgid "Please do not use any spaces in this field."
msgstr "Merci de ne pas utiliser d'espace dans ce champ."
#: cms/static/js/views/utils/view_utils.js
msgid "Please do not use any spaces or special characters in this field."
msgstr ""
"Merci de ne pas utiliser d'espace ou de caractère spécial dans ce champ."
#: cms/static/js/views/utils/xblock_utils.js
msgid "component"
msgstr "composant"
@@ -5356,11 +5415,526 @@ msgstr "Actions"
msgid "Due Date"
msgstr "Date d'échéance"
#: cms/templates/js/paging-header.underscore
#: common/static/common/templates/components/paging-footer.underscore
#: common/static/common/templates/discussion/pagination.underscore
msgid "Previous"
msgstr ""
#: cms/templates/js/previous-video-upload-list.underscore
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
#: lms/templates/verify_student/enrollment_confirmation_step.underscore
msgid "Status"
msgstr "Statut"
#: common/static/common/templates/image-modal.underscore
msgid "Large"
msgstr ""
#: common/static/common/templates/image-modal.underscore
msgid "Zoom In"
msgstr ""
#: common/static/common/templates/image-modal.underscore
msgid "Zoom Out"
msgstr ""
#: common/static/common/templates/components/paging-footer.underscore
msgid "Page number"
msgstr ""
#: common/static/common/templates/components/paging-footer.underscore
msgid "Enter the page number you'd like to quickly navigate to."
msgstr ""
#: common/static/common/templates/components/paging-header.underscore
msgid "Sorted by"
msgstr ""
#: common/static/common/templates/components/search-field.underscore
msgid "Clear search"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "DISCUSSION HOME:"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
#: lms/templates/commerce/provider.underscore
#: lms/templates/commerce/receipt.underscore
#: lms/templates/discovery/course_card.underscore
msgid "gettext("
msgstr "gettext("
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Find discussions"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Focus in on specific topics"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Search for specific posts"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Sort by date, vote, or comments"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Engage with posts"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Upvote posts and good responses"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Report Forum Misuse"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Follow posts for updates"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Receive updates"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Toggle Notifications Setting"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid ""
"Check this box to receive an email digest once a day notifying you about "
"new, unread activity from posts you are following."
msgstr ""
#: common/static/common/templates/discussion/forum-action-answer.underscore
msgid "Mark as Answer"
msgstr ""
#: common/static/common/templates/discussion/forum-action-answer.underscore
msgid "Unmark as Answer"
msgstr ""
#: common/static/common/templates/discussion/forum-action-close.underscore
msgid "Open"
msgstr ""
#: common/static/common/templates/discussion/forum-action-endorse.underscore
msgid "Endorse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-endorse.underscore
msgid "Unendorse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-follow.underscore
msgid "Follow"
msgstr ""
#: common/static/common/templates/discussion/forum-action-follow.underscore
msgid "Unfollow"
msgstr ""
#: common/static/common/templates/discussion/forum-action-pin.underscore
msgid "Pin"
msgstr ""
#: common/static/common/templates/discussion/forum-action-pin.underscore
msgid "Unpin"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Report abuse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Report"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Unreport"
msgstr ""
#: common/static/common/templates/discussion/forum-action-vote.underscore
msgid "Vote for this post,"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Visible To:"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "All Groups"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid ""
"Discussion admins, moderators, and TAs can make their posts visible to all "
"students or specify a single cohort."
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Title:"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Add a clear and descriptive title to encourage participation."
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Enter your question or comment"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "follow this post"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "post anonymously"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "post anonymously to classmates"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Add Post"
msgstr ""
#: common/static/common/templates/discussion/post-user-display.underscore
msgid "Community TA"
msgstr ""
#: common/static/common/templates/discussion/profile-thread.underscore
#: common/static/common/templates/discussion/thread.underscore
msgid "This thread is closed."
msgstr ""
#: common/static/common/templates/discussion/profile-thread.underscore
msgid "View discussion"
msgstr ""
#: common/static/common/templates/discussion/response-comment-edit.underscore
msgid "Editing comment"
msgstr ""
#: common/static/common/templates/discussion/response-comment-edit.underscore
msgid "Update comment"
msgstr ""
#: common/static/common/templates/discussion/response-comment-show.underscore
#, python-format
msgid "posted %(time_ago)s by %(author)s"
msgstr ""
#: common/static/common/templates/discussion/response-comment-show.underscore
#: common/static/common/templates/discussion/thread-response-show.underscore
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Reported"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Editing post"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Edit post title"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Update post"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "discussion"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "answered question"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "unanswered question"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Pinned"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "Following"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "By: Staff"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "By: Community TA"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#: common/static/common/templates/discussion/thread-response-show.underscore
msgid "fmt"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#, python-format
msgid ""
"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s "
"unread comments)%(span_close)s"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#, python-format
msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-edit.underscore
msgid "Editing response"
msgstr ""
#: common/static/common/templates/discussion/thread-response-edit.underscore
msgid "Update response"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "marked as answer %(time_ago)s by %(user)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "marked as answer %(time_ago)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "endorsed %(time_ago)s by %(user)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "endorsed %(time_ago)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response.underscore
msgid "fmts"
msgstr ""
#: common/static/common/templates/discussion/thread-response.underscore
msgid "Add a comment"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "This post is visible only to %(group_name)s."
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
msgid "This post is visible to everyone."
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "%(post_type)s posted %(time_ago)s by %(author)s"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Closed"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "Related to: %(courseware_title_linked)s"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Post type:"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Question"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Discussion"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid ""
"Questions raise issues that need answers. Discussions share ideas and start "
"conversations."
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Add a Response"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Post a response:"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Expand discussion"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Collapse discussion"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Topic Area:"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Discussion topics; current selection is:"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Filter topics"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Add your post to a relevant topic to help others find it."
msgstr ""
#: common/static/common/templates/discussion/user-profile.underscore
msgid "Active Threads"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates.underscore
msgid "username or email"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "No results"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Course Key"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Download URL"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Grade"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Last Updated"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Download the user's certificate"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Not available"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Regenerate"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Regenerate the user's certificate"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Your team could not be created."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Your team could not be updated."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid ""
"Enter information to describe your team. You cannot change these details "
"after you create the team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Optional Characteristics"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid ""
"Help other learners decide whether to join your team by specifying some "
"characteristics for your team. Choose carefully, because fewer people might "
"be interested in joining your team if it seems too restrictive."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Create team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Update team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel team creating."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel team updating."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-actions.underscore
msgid "Are you having trouble finding a team to join?"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
msgid "Join Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "New Post"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team Details"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "You are a member of this team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team member profiles"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team capacity"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "country"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "language"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Leave Team"
msgstr ""
#: lms/static/js/fixtures/donation.underscore
#: lms/templates/dashboard/donation.underscore
msgid "Donate"
msgstr "Faire un don"
#: lms/templates/ccx/schedule.underscore
msgid "Expand All"
msgstr ""
@@ -5401,12 +5975,6 @@ msgstr ""
msgid "Subsection"
msgstr ""
#: lms/templates/commerce/provider.underscore
#: lms/templates/commerce/receipt.underscore
#: lms/templates/discovery/course_card.underscore
msgid "gettext("
msgstr "gettext("
#: lms/templates/commerce/provider.underscore
#, python-format
msgid "<img src='%s' alt='%s'></image>"
@@ -5503,10 +6071,6 @@ msgstr ""
msgid "End My Exam"
msgstr ""
#: lms/templates/dashboard/donation.underscore
msgid "Donate"
msgstr "Faire un don"
#: lms/templates/discovery/course_card.underscore
msgid "LEARN MORE"
msgstr "EN SAVOIR PLUS"
@@ -6483,6 +7047,16 @@ msgstr "Glisser déposer ou cliquer ici pour importer des fichiers vidéo."
msgid "status"
msgstr "statut"
#: cms/templates/js/add-xblock-component-button.underscore
msgid "Add Component:"
msgstr ""
#: cms/templates/js/add-xblock-component-menu-problem.underscore
#: cms/templates/js/add-xblock-component-menu.underscore
#, python-format
msgid "%(type)s Component Template Menu"
msgstr ""
#: cms/templates/js/add-xblock-component-menu-problem.underscore
msgid "Common Problem Types"
msgstr "Types d'exercices classiques"
@@ -6557,6 +7131,11 @@ msgstr "Identifiant"
msgid "Certificate Details"
msgstr ""
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
msgid "Course Title"
msgstr ""
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
msgid "Course Title Override"
@@ -6601,19 +7180,13 @@ msgid ""
msgstr ""
#: cms/templates/js/certificate-editor.underscore
msgid "Add Signatory"
msgid "Add Additional Signatory"
msgstr ""
#: cms/templates/js/certificate-editor.underscore
msgid "(Up to 4 signatories are allowed for a certificate)"
msgstr ""
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/group-configuration-editor.underscore
msgid "Create"
msgstr "Créer"
#: cms/templates/js/certificate-web-preview.underscore
msgid "Choose mode"
msgstr ""
@@ -7055,10 +7628,6 @@ msgstr "Vous n'avez encore ajouté aucun manuel à ce cours."
msgid "Add your first textbook"
msgstr "Ajouter votre premier manuel"
#: cms/templates/js/paging-header.underscore
msgid "Previous"
msgstr ""
#: cms/templates/js/previous-video-upload-list.underscore
msgid "Previous Uploads"
msgstr ""

Binary file not shown.

View File

@@ -61,7 +61,7 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-21 14:18+0000\n"
"POT-Creation-Date: 2015-09-04 14:07+0000\n"
"PO-Revision-Date: 2015-05-28 20:00+0000\n"
"Last-Translator: Nadav Stark <nadav@yeda.org.il>\n"
"Language-Team: Hebrew (http://www.transifex.com/open-edx/edx-platform/language/he/)\n"
@@ -1215,10 +1215,6 @@ msgstr ""
msgid "incorrect"
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "partially correct"
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "incomplete"
msgstr ""
@@ -1241,10 +1237,6 @@ msgstr ""
msgid "This is incorrect."
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "This is partially correct."
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "This is unanswered."
msgstr ""
@@ -4550,7 +4542,14 @@ msgid "{month} {day}, {year}"
msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid "a course of study offered by {partner_name}, through {platform_name}."
msgid ""
"a course of study offered by {partner_short_name}, an online learning "
"initiative of {partner_long_name} through {platform_name}."
msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"a course of study offered by {partner_short_name}, through {platform_name}."
msgstr ""
#. Translators: Accomplishments describe the awards/certifications obtained by
@@ -4650,13 +4649,13 @@ msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"This is a valid {platform_name} certificate for {user_name}, who "
"participated in {partner_name} {course_number}"
"participated in {partner_short_name} {course_number}"
msgstr ""
#. Translators: This text is bound to the HTML 'title' element of the page
#. and appears in the browser title bar
#: lms/djangoapps/certificates/views/webview.py
msgid "{partner_name} {course_number} Certificate | {platform_name}"
msgid "{partner_short_name} {course_number} Certificate | {platform_name}"
msgstr ""
#. Translators: This text fragment appears after the student's name
@@ -4813,6 +4812,14 @@ msgid ""
"{payment_support_link}."
msgstr ""
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "{course_id} is not a valid course key."
msgstr ""
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "Course {course_id} does not exist."
msgstr ""
#: lms/djangoapps/course_wiki/tab.py lms/djangoapps/course_wiki/views.py
#: lms/templates/wiki/base.html
msgid "Wiki"
@@ -5333,6 +5340,23 @@ msgstr ""
msgid "File is not attached."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid "Could not find problem with this location."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"The problem responses report is being created. To view the status of the "
"report, see Pending Tasks below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A problem responses report generation task is already in progress. Check the"
" 'Pending Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid "Invoice number '{num}' does not exist."
msgstr ""
@@ -5719,6 +5743,10 @@ msgstr ""
msgid "CourseMode price updated successfully"
msgstr ""
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "No end date set"
msgstr ""
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "Enrollment data is now available in {dashboard_link}."
msgstr ""
@@ -5816,18 +5844,6 @@ msgstr ""
msgid "Grades for assignment \"{name}\""
msgstr ""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Found {num} records to dump."
msgstr ""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Couldn't find module with that urlname."
msgstr ""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Student state for problem {problem}"
msgstr ""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Grades from {course_id}"
msgstr ""
@@ -5991,6 +6007,12 @@ msgstr ""
msgid "emailed"
msgstr ""
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr ""
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -6003,12 +6025,6 @@ msgstr ""
msgid "problem distribution graded"
msgstr ""
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr ""
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -7392,6 +7408,7 @@ msgid "Optional language the team uses as ISO 639-1 code."
msgstr ""
#: lms/djangoapps/teams/plugins.py
#: lms/djangoapps/teams/templates/teams/teams.html
msgid "Teams"
msgstr ""
@@ -7404,11 +7421,11 @@ msgid "course_id must be provided"
msgstr ""
#: lms/djangoapps/teams/views.py
msgid "The supplied topic id {topic_id} is not valid"
msgid "text_search and order_by cannot be provided together"
msgstr ""
#: lms/djangoapps/teams/views.py
msgid "text_search is not yet supported."
msgid "The supplied topic id {topic_id} is not valid"
msgstr ""
#. Translators: 'ordering' is a string describing a way
@@ -9112,6 +9129,10 @@ msgstr ""
msgid "Sign Out"
msgstr ""
#: common/lib/capa/capa/templates/codeinput.html
msgid "{programming_language} editor"
msgstr ""
#: common/templates/license.html
msgid "All Rights Reserved"
msgstr ""
@@ -11605,7 +11626,9 @@ msgid "Section:"
msgstr ""
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid "Problem urlname:"
msgid ""
"To download a CSV listing student responses to a given problem, visit the "
"Data Download section of the Instructor Dashboard."
msgstr ""
#: lms/templates/courseware/legacy_instructor_dashboard.html
@@ -13377,6 +13400,20 @@ msgstr ""
msgid "Generate Proctored Exam Results Report"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"To generate a CSV file that lists all student answers to a given problem, "
"enter the location of the problem (from its Staff Debug Info)."
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Problem location: "
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Download a CSV of problem responses"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"For smaller courses, click to list profile information for enrolled students"
@@ -15674,41 +15711,50 @@ msgid "This module is not enabled."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"Upon successful completion of your course, learners receive a certificate to"
" acknowledge their accomplishment. If you are a course team member with the "
"Admin role in Studio, you can configure your course certificate."
msgid "Working with Certificates"
msgstr ""
#: cms/templates/certificates.html
msgid ""
"Click {em_start}Add your first certificate{em_end} to add a certificate "
"configuration. Upload the organization logo to be used on the certificate, "
"and specify at least one signatory. You can include up to four signatories "
"for a certificate. You can also upload a signature image file for each "
"signatory. {em_start}Note:{em_end} Signature images are used only for "
"verified certificates. Optionally, specify a different course title to use "
"on your course certificate. You might want to use a different title if, for "
"example, the official course name is too long to display well on a "
"certificate."
"Specify a course title to use on the certificate if the course's official "
"title is too long to be displayed well."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"Select a course mode and click {em_start}Preview Certificate{em_end} to "
"preview the certificate that a learner in the selected enrollment track "
"would receive. When the certificate is ready for issuing, click "
"{em_start}Activate.{em_end} To stop issuing an active certificate, click "
"{em_start}Deactivate{em_end}."
"For verified certificates, specify between one and four signatories and "
"upload the associated images."
msgstr ""
#: cms/templates/certificates.html
msgid ""
" To edit the certificate configuration, hover over the top right corner of "
"the form and click {em_start}Edit{em_end}. To delete a certificate, hover "
"over the top right corner of the form and click the delete icon. In general,"
" do not delete certificates after a course has started, because some "
"certificates might already have been issued to learners."
"To edit or delete a certificate before it is activated, hover over the top "
"right corner of the form and select {em_start}Edit{em_end} or the delete "
"icon."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"To view a sample certificate, choose a course mode and select "
"{em_start}Preview Certificate{em_end}."
msgstr ""
#: cms/templates/certificates.html
msgid "Issuing Certificates to Learners"
msgstr ""
#: cms/templates/certificates.html
msgid ""
"To begin issuing certificates, a course team member with the Admin role "
"selects {em_start}Activate{em_end}. Course team members without the Admin "
"role cannot edit or delete an activated certificate."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"{em_start}Do not{em_end} delete certificates after a course has started; "
"learners who have already earned certificates will no longer be able to "
"access them."
msgstr ""
#: cms/templates/certificates.html

View File

@@ -44,8 +44,8 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-21 14:17+0000\n"
"PO-Revision-Date: 2015-08-21 02:41+0000\n"
"POT-Creation-Date: 2015-09-04 14:06+0000\n"
"PO-Revision-Date: 2015-09-04 14:08+0000\n"
"Last-Translator: Sarina Canelake <sarina@edx.org>\n"
"Language-Team: Hebrew (http://www.transifex.com/open-edx/edx-platform/language/he/)\n"
"MIME-Version: 1.0\n"
@@ -91,8 +91,8 @@ msgstr ""
#: cms/static/js/views/show_textbook.js cms/static/js/views/validation.js
#: cms/static/js/views/modals/base_modal.js
#: cms/static/js/views/modals/course_outline_modals.js
#: cms/static/js/views/utils/view_utils.js
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: common/static/common/js/components/utils/view_utils.js
#: cms/templates/js/add-xblock-component-menu-problem.underscore
#: cms/templates/js/add-xblock-component-menu.underscore
#: cms/templates/js/certificate-editor.underscore
@@ -103,6 +103,11 @@ msgstr ""
#: cms/templates/js/group-configuration-editor.underscore
#: cms/templates/js/section-name-edit.underscore
#: cms/templates/js/xblock-string-field-editor.underscore
#: common/static/common/templates/discussion/new-post.underscore
#: common/static/common/templates/discussion/response-comment-edit.underscore
#: common/static/common/templates/discussion/thread-edit.underscore
#: common/static/common/templates/discussion/thread-response-edit.underscore
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
#: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore
msgid "Cancel"
msgstr ""
@@ -123,6 +128,7 @@ msgstr ""
#: cms/templates/js/show-textbook.underscore
#: cms/templates/js/signatory-editor.underscore
#: cms/templates/js/xblock-outline.underscore
#: common/static/common/templates/discussion/forum-action-delete.underscore
msgid "Delete"
msgstr ""
@@ -203,6 +209,8 @@ msgstr ""
#: cms/static/js/views/modals/edit_xblock.js
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/signatory-editor.underscore
#: common/static/common/templates/image-modal.underscore
#: common/static/common/templates/discussion/forum-action-close.underscore
msgid "Close"
msgstr ""
@@ -292,6 +300,8 @@ msgstr ""
#: common/lib/xmodule/xmodule/js/src/combinedopenended/display.js
#: lms/static/coffee/src/staff_grading/staff_grading.js
#: common/static/common/templates/discussion/thread-response.underscore
#: common/static/common/templates/discussion/thread.underscore
#: lms/templates/verify_student/incourse_reverify.underscore
msgid "Submit"
msgstr ""
@@ -726,6 +736,7 @@ msgstr ""
#: cms/templates/js/show-textbook.underscore
#: cms/templates/js/signatory-details.underscore
#: cms/templates/js/xblock-string-field-editor.underscore
#: common/static/common/templates/discussion/forum-action-edit.underscore
msgid "Edit"
msgstr ""
@@ -813,9 +824,11 @@ msgstr ""
msgid "Formats"
msgstr ""
#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: common/static/common/templates/image-modal.underscore
msgid "Fullscreen"
msgstr ""
@@ -1131,6 +1144,8 @@ msgstr ""
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/paging-header.underscore
#: common/static/common/templates/components/paging-footer.underscore
#: common/static/common/templates/discussion/pagination.underscore
msgid "Next"
msgstr ""
@@ -1840,6 +1855,7 @@ msgstr ""
#: common/static/coffee/src/discussion/utils.js
#: common/static/coffee/src/discussion/views/discussion_thread_list_view.js
#: common/static/coffee/src/discussion/views/discussion_topic_menu_view.js
#: common/static/common/templates/discussion/pagination.underscore
msgid "…"
msgstr ""
@@ -2014,6 +2030,8 @@ msgid "Your post will be discarded."
msgstr ""
#: common/static/coffee/src/discussion/views/response_comment_show_view.js
#: common/static/common/templates/discussion/post-user-display.underscore
#: common/static/common/templates/discussion/profile-thread.underscore
msgid "anonymous"
msgstr ""
@@ -2029,6 +2047,18 @@ msgstr ""
msgid "Are you sure you want to delete this response?"
msgstr ""
#: common/static/common/js/components/utils/view_utils.js
msgid "Required field."
msgstr ""
#: common/static/common/js/components/utils/view_utils.js
msgid "Please do not use any spaces in this field."
msgstr ""
#: common/static/common/js/components/utils/view_utils.js
msgid "Please do not use any spaces or special characters in this field."
msgstr ""
#: common/static/common/js/components/views/paging_header.js
msgid "Showing %(first_index)s out of %(num_items)s total"
msgstr ""
@@ -2194,6 +2224,7 @@ msgstr ""
#: common/static/js/vendor/ova/catch/js/catch.js
#: lms/static/js/courseware/credit_progress.js
#: common/static/common/templates/discussion/forum-actions.underscore
#: lms/templates/discovery/facet.underscore
#: lms/templates/edxnotes/note-item.underscore
msgid "More"
@@ -2212,6 +2243,8 @@ msgid "Public"
msgstr ""
#: common/static/js/vendor/ova/catch/js/catch.js
#: common/static/common/templates/components/search-field.underscore
#: lms/djangoapps/support/static/support/templates/certificates.underscore
msgid "Search"
msgstr ""
@@ -2273,13 +2306,16 @@ msgid "An unexpected error occurred. Please try again."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/team.js
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
#: lms/templates/edxnotes/tab-item.underscore
msgid "name"
msgid "last activity"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/team.js
msgid "open_slots"
msgid "open slots"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
#: lms/templates/edxnotes/tab-item.underscore
msgid "name"
msgstr ""
#. Translators: This refers to the number of teams (a count of how many teams
@@ -2288,6 +2324,17 @@ msgstr ""
msgid "team count"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/group-configuration-editor.underscore
msgid "Create"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
msgid "Update"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
msgid "Team Name (Required) *"
msgstr ""
@@ -2312,6 +2359,7 @@ msgid "Language"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid ""
"The language that team members primarily use to communicate with each other."
msgstr ""
@@ -2322,6 +2370,7 @@ msgid "Country"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/edit_team.js
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "The country that team members primarily identify with."
msgstr ""
@@ -2354,20 +2403,48 @@ msgstr ""
msgid "You are not currently a member of any team."
msgstr ""
#. Translators: "and others" refers to fact that additional members of a team
#. exist that are not displayed.
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "and others"
msgstr ""
#. Translators: 'date' is a placeholder for a fuzzy, relative timestamp (see:
#. https://github.com/rmm5t/jquery-timeago)
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "Last Activity %(date)s"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_card.js
msgid "View %(span_start)s %(team_name)s %(span_end)s"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "An error occurred. Try again."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
msgid "Leave this team?"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
msgid ""
"If you leave, you can no longer post in this team's discussions. Your place "
"will be available to another learner."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_profile.js
#: lms/static/js/verify_student/views/reverify_view.js
#: lms/templates/verify_student/review_photos_step.underscore
msgid "Confirm"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "You already belong to another team."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/team_join.js
#: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
msgid "This team is full."
msgstr ""
@@ -2386,13 +2463,13 @@ msgid "teams"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"See all teams in your course, organized by topic. Join a team to collaborate"
" with other learners who are interested in the same topic as you are."
msgid "Teams"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Teams"
msgid ""
"See all teams in your course, organized by topic. Join a team to collaborate"
" with other learners who are interested in the same topic as you are."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
@@ -2400,22 +2477,47 @@ msgid "My Team"
msgstr ""
#. Translators: sr_start and sr_end surround text meant only for screen
#. readers. The whole string will be shown to users as "Browse teams" if they
#. are using a screenreader, and "Browse" otherwise.
#. readers.
#. The whole string will be shown to users as "Browse teams" if they are using
#. a
#. screenreader, and "Browse" otherwise.
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Browse %(sr_start)s teams %(sr_end)s"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Create a new team if you can't find existing teams to join, or if you would "
"like to learn with friends you know."
msgid "Team Search"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Showing results for \"%(searchString)s\""
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Create a New Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Create a new team if you can't find an existing team to join, or if you "
"would like to learn with friends you know."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
#: lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
msgid "Edit Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"If you make significant changes, make sure you notify members of the team "
"before making these changes."
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "Search teams"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid "All Topics"
msgstr ""
@@ -2438,15 +2540,27 @@ msgid_plural "%(team_count)s Teams"
msgstr[0] ""
msgstr[1] ""
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "Topic"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "View Teams in the %(topic_name)s Topic"
msgstr ""
#. Translators: this string is shown at the bottom of the teams page
#. to find a team to join or else to create a new one. There are three
#. links that need to be included in the message:
#. 1. Browse teams in other topics
#. 2. search teams
#. 3. create a new team
#. Be careful to start each link with the appropriate start indicator
#. (e.g. {browse_span_start} for #1) and finish it with {span_end}.
#: lms/djangoapps/teams/static/teams/js/views/topic_teams.js
msgid ""
"Try {browse_span_start}browsing all teams{span_end} or "
"{search_span_start}searching team descriptions{span_end}. If you still can't"
" find a team to join, {create_span_start}create a new team in this "
"{browse_span_start}Browse teams in other topics{span_end} or "
"{search_span_start}search teams{span_end} in this topic. If you still can't "
"find a team to join, {create_span_start}create a new team in this "
"topic{span_end}."
msgstr ""
@@ -3784,11 +3898,6 @@ msgstr ""
msgid "Review your info"
msgstr ""
#: lms/static/js/verify_student/views/reverify_view.js
#: lms/templates/verify_student/review_photos_step.underscore
msgid "Confirm"
msgstr ""
#: lms/static/js/verify_student/views/step_view.js
msgid "An error has occurred. Please try reloading the page."
msgstr ""
@@ -4151,6 +4260,7 @@ msgstr ""
#: cms/static/js/factories/manage_users.js
#: cms/static/js/factories/manage_users_lib.js
#: common/static/common/templates/discussion/post-user-display.underscore
msgid "Staff"
msgstr ""
@@ -4334,6 +4444,7 @@ msgid "Date Added"
msgstr ""
#: cms/static/js/views/assets.js cms/templates/js/asset-library.underscore
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Type"
msgstr ""
@@ -4890,18 +5001,6 @@ msgid ""
"more than <%=limit%> characters."
msgstr ""
#: cms/static/js/views/utils/view_utils.js
msgid "Required field."
msgstr ""
#: cms/static/js/views/utils/view_utils.js
msgid "Please do not use any spaces in this field."
msgstr ""
#: cms/static/js/views/utils/view_utils.js
msgid "Please do not use any spaces or special characters in this field."
msgstr ""
#: cms/static/js/views/utils/xblock_utils.js
msgid "component"
msgstr ""
@@ -4991,11 +5090,526 @@ msgstr ""
msgid "Due Date"
msgstr ""
#: cms/templates/js/paging-header.underscore
#: common/static/common/templates/components/paging-footer.underscore
#: common/static/common/templates/discussion/pagination.underscore
msgid "Previous"
msgstr ""
#: cms/templates/js/previous-video-upload-list.underscore
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
#: lms/templates/verify_student/enrollment_confirmation_step.underscore
msgid "Status"
msgstr ""
#: common/static/common/templates/image-modal.underscore
msgid "Large"
msgstr ""
#: common/static/common/templates/image-modal.underscore
msgid "Zoom In"
msgstr ""
#: common/static/common/templates/image-modal.underscore
msgid "Zoom Out"
msgstr ""
#: common/static/common/templates/components/paging-footer.underscore
msgid "Page number"
msgstr ""
#: common/static/common/templates/components/paging-footer.underscore
msgid "Enter the page number you'd like to quickly navigate to."
msgstr ""
#: common/static/common/templates/components/paging-header.underscore
msgid "Sorted by"
msgstr ""
#: common/static/common/templates/components/search-field.underscore
msgid "Clear search"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "DISCUSSION HOME:"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
#: lms/templates/commerce/provider.underscore
#: lms/templates/commerce/receipt.underscore
#: lms/templates/discovery/course_card.underscore
msgid "gettext("
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Find discussions"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Focus in on specific topics"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Search for specific posts"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Sort by date, vote, or comments"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Engage with posts"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Upvote posts and good responses"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Report Forum Misuse"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Follow posts for updates"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Receive updates"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid "Toggle Notifications Setting"
msgstr ""
#: common/static/common/templates/discussion/discussion-home.underscore
msgid ""
"Check this box to receive an email digest once a day notifying you about "
"new, unread activity from posts you are following."
msgstr ""
#: common/static/common/templates/discussion/forum-action-answer.underscore
msgid "Mark as Answer"
msgstr ""
#: common/static/common/templates/discussion/forum-action-answer.underscore
msgid "Unmark as Answer"
msgstr ""
#: common/static/common/templates/discussion/forum-action-close.underscore
msgid "Open"
msgstr ""
#: common/static/common/templates/discussion/forum-action-endorse.underscore
msgid "Endorse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-endorse.underscore
msgid "Unendorse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-follow.underscore
msgid "Follow"
msgstr ""
#: common/static/common/templates/discussion/forum-action-follow.underscore
msgid "Unfollow"
msgstr ""
#: common/static/common/templates/discussion/forum-action-pin.underscore
msgid "Pin"
msgstr ""
#: common/static/common/templates/discussion/forum-action-pin.underscore
msgid "Unpin"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Report abuse"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Report"
msgstr ""
#: common/static/common/templates/discussion/forum-action-report.underscore
msgid "Unreport"
msgstr ""
#: common/static/common/templates/discussion/forum-action-vote.underscore
msgid "Vote for this post,"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Visible To:"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "All Groups"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid ""
"Discussion admins, moderators, and TAs can make their posts visible to all "
"students or specify a single cohort."
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Title:"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Add a clear and descriptive title to encourage participation."
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Enter your question or comment"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "follow this post"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "post anonymously"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "post anonymously to classmates"
msgstr ""
#: common/static/common/templates/discussion/new-post.underscore
msgid "Add Post"
msgstr ""
#: common/static/common/templates/discussion/post-user-display.underscore
msgid "Community TA"
msgstr ""
#: common/static/common/templates/discussion/profile-thread.underscore
#: common/static/common/templates/discussion/thread.underscore
msgid "This thread is closed."
msgstr ""
#: common/static/common/templates/discussion/profile-thread.underscore
msgid "View discussion"
msgstr ""
#: common/static/common/templates/discussion/response-comment-edit.underscore
msgid "Editing comment"
msgstr ""
#: common/static/common/templates/discussion/response-comment-edit.underscore
msgid "Update comment"
msgstr ""
#: common/static/common/templates/discussion/response-comment-show.underscore
#, python-format
msgid "posted %(time_ago)s by %(author)s"
msgstr ""
#: common/static/common/templates/discussion/response-comment-show.underscore
#: common/static/common/templates/discussion/thread-response-show.underscore
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Reported"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Editing post"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Edit post title"
msgstr ""
#: common/static/common/templates/discussion/thread-edit.underscore
msgid "Update post"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "discussion"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "answered question"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "unanswered question"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Pinned"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "Following"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "By: Staff"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
msgid "By: Community TA"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#: common/static/common/templates/discussion/thread-response-show.underscore
msgid "fmt"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#, python-format
msgid ""
"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s "
"unread comments)%(span_close)s"
msgstr ""
#: common/static/common/templates/discussion/thread-list-item.underscore
#, python-format
msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-edit.underscore
msgid "Editing response"
msgstr ""
#: common/static/common/templates/discussion/thread-response-edit.underscore
msgid "Update response"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "marked as answer %(time_ago)s by %(user)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "marked as answer %(time_ago)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "endorsed %(time_ago)s by %(user)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response-show.underscore
#, python-format
msgid "endorsed %(time_ago)s"
msgstr ""
#: common/static/common/templates/discussion/thread-response.underscore
msgid "fmts"
msgstr ""
#: common/static/common/templates/discussion/thread-response.underscore
msgid "Add a comment"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "This post is visible only to %(group_name)s."
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
msgid "This post is visible to everyone."
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "%(post_type)s posted %(time_ago)s by %(author)s"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
msgid "Closed"
msgstr ""
#: common/static/common/templates/discussion/thread-show.underscore
#, python-format
msgid "Related to: %(courseware_title_linked)s"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Post type:"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Question"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid "Discussion"
msgstr ""
#: common/static/common/templates/discussion/thread-type.underscore
msgid ""
"Questions raise issues that need answers. Discussions share ideas and start "
"conversations."
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Add a Response"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Post a response:"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Expand discussion"
msgstr ""
#: common/static/common/templates/discussion/thread.underscore
msgid "Collapse discussion"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Topic Area:"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Discussion topics; current selection is:"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Filter topics"
msgstr ""
#: common/static/common/templates/discussion/topic.underscore
msgid "Add your post to a relevant topic to help others find it."
msgstr ""
#: common/static/common/templates/discussion/user-profile.underscore
msgid "Active Threads"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates.underscore
msgid "username or email"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "No results"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Course Key"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Download URL"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Grade"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Last Updated"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Download the user's certificate"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Not available"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Regenerate"
msgstr ""
#: lms/djangoapps/support/static/support/templates/certificates_results.underscore
msgid "Regenerate the user's certificate"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Your team could not be created."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Your team could not be updated."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid ""
"Enter information to describe your team. You cannot change these details "
"after you create the team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Optional Characteristics"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid ""
"Help other learners decide whether to join your team by specifying some "
"characteristics for your team. Choose carefully, because fewer people might "
"be interested in joining your team if it seems too restrictive."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Create team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Update team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel team creating."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/edit-team.underscore
msgid "Cancel team updating."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-actions.underscore
msgid "Are you having trouble finding a team to join?"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
msgid "Join Team"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "New Post"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team Details"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "You are a member of this team."
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team member profiles"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Team capacity"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "country"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "language"
msgstr ""
#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore
msgid "Leave Team"
msgstr ""
#: lms/static/js/fixtures/donation.underscore
#: lms/templates/dashboard/donation.underscore
msgid "Donate"
msgstr ""
#: lms/templates/ccx/schedule.underscore
msgid "Expand All"
msgstr ""
@@ -5036,12 +5650,6 @@ msgstr ""
msgid "Subsection"
msgstr ""
#: lms/templates/commerce/provider.underscore
#: lms/templates/commerce/receipt.underscore
#: lms/templates/discovery/course_card.underscore
msgid "gettext("
msgstr ""
#: lms/templates/commerce/provider.underscore
#, python-format
msgid "<img src='%s' alt='%s'></image>"
@@ -5131,10 +5739,6 @@ msgstr ""
msgid "End My Exam"
msgstr ""
#: lms/templates/dashboard/donation.underscore
msgid "Donate"
msgstr ""
#: lms/templates/discovery/course_card.underscore
msgid "LEARN MORE"
msgstr ""
@@ -6051,6 +6655,16 @@ msgstr ""
msgid "status"
msgstr ""
#: cms/templates/js/add-xblock-component-button.underscore
msgid "Add Component:"
msgstr ""
#: cms/templates/js/add-xblock-component-menu-problem.underscore
#: cms/templates/js/add-xblock-component-menu.underscore
#, python-format
msgid "%(type)s Component Template Menu"
msgstr ""
#: cms/templates/js/add-xblock-component-menu-problem.underscore
msgid "Common Problem Types"
msgstr ""
@@ -6125,6 +6739,11 @@ msgstr ""
msgid "Certificate Details"
msgstr ""
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
msgid "Course Title"
msgstr ""
#: cms/templates/js/certificate-details.underscore
#: cms/templates/js/certificate-editor.underscore
msgid "Course Title Override"
@@ -6169,19 +6788,13 @@ msgid ""
msgstr ""
#: cms/templates/js/certificate-editor.underscore
msgid "Add Signatory"
msgid "Add Additional Signatory"
msgstr ""
#: cms/templates/js/certificate-editor.underscore
msgid "(Up to 4 signatories are allowed for a certificate)"
msgstr ""
#: cms/templates/js/certificate-editor.underscore
#: cms/templates/js/content-group-editor.underscore
#: cms/templates/js/group-configuration-editor.underscore
msgid "Create"
msgstr ""
#: cms/templates/js/certificate-web-preview.underscore
msgid "Choose mode"
msgstr ""
@@ -6606,10 +7219,6 @@ msgstr ""
msgid "Add your first textbook"
msgstr ""
#: cms/templates/js/paging-header.underscore
msgid "Previous"
msgstr ""
#: cms/templates/js/previous-video-upload-list.underscore
msgid "Previous Uploads"
msgstr ""

Binary file not shown.

View File

@@ -72,7 +72,7 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-08-21 14:18+0000\n"
"POT-Creation-Date: 2015-09-04 14:07+0000\n"
"PO-Revision-Date: 2015-06-28 20:21+0000\n"
"Last-Translator: ria1234 <contactpayal@yahoo.com.au>\n"
"Language-Team: Hindi (http://www.transifex.com/open-edx/edx-platform/language/hi/)\n"
@@ -1227,10 +1227,6 @@ msgstr ""
msgid "incorrect"
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "partially correct"
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "incomplete"
msgstr ""
@@ -1253,10 +1249,6 @@ msgstr ""
msgid "This is incorrect."
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "This is partially correct."
msgstr ""
#: common/lib/capa/capa/inputtypes.py
msgid "This is unanswered."
msgstr ""
@@ -4587,7 +4579,14 @@ msgid "{month} {day}, {year}"
msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid "a course of study offered by {partner_name}, through {platform_name}."
msgid ""
"a course of study offered by {partner_short_name}, an online learning "
"initiative of {partner_long_name} through {platform_name}."
msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"a course of study offered by {partner_short_name}, through {platform_name}."
msgstr ""
#. Translators: Accomplishments describe the awards/certifications obtained by
@@ -4687,13 +4686,13 @@ msgstr ""
#: lms/djangoapps/certificates/views/webview.py
msgid ""
"This is a valid {platform_name} certificate for {user_name}, who "
"participated in {partner_name} {course_number}"
"participated in {partner_short_name} {course_number}"
msgstr ""
#. Translators: This text is bound to the HTML 'title' element of the page
#. and appears in the browser title bar
#: lms/djangoapps/certificates/views/webview.py
msgid "{partner_name} {course_number} Certificate | {platform_name}"
msgid "{partner_short_name} {course_number} Certificate | {platform_name}"
msgstr ""
#. Translators: This text fragment appears after the student's name
@@ -4849,6 +4848,14 @@ msgid ""
"{payment_support_link}."
msgstr ""
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "{course_id} is not a valid course key."
msgstr ""
#: lms/djangoapps/commerce/api/v1/serializers.py
msgid "Course {course_id} does not exist."
msgstr ""
#: lms/djangoapps/course_wiki/tab.py lms/djangoapps/course_wiki/views.py
#: lms/templates/wiki/base.html
msgid "Wiki"
@@ -5384,6 +5391,23 @@ msgstr ""
msgid "File is not attached."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid "Could not find problem with this location."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"The problem responses report is being created. To view the status of the "
"report, see Pending Tasks below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A problem responses report generation task is already in progress. Check the"
" 'Pending Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid "Invoice number '{num}' does not exist."
msgstr ""
@@ -5770,6 +5794,10 @@ msgstr ""
msgid "CourseMode price updated successfully"
msgstr ""
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "No end date set"
msgstr ""
#: lms/djangoapps/instructor/views/instructor_dashboard.py
msgid "Enrollment data is now available in {dashboard_link}."
msgstr ""
@@ -5865,18 +5893,6 @@ msgstr ""
msgid "Grades for assignment \"{name}\""
msgstr ""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Found {num} records to dump."
msgstr ""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Couldn't find module with that urlname."
msgstr ""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Student state for problem {problem}"
msgstr ""
#: lms/djangoapps/instructor/views/legacy.py
msgid "Grades from {course_id}"
msgstr ""
@@ -6040,6 +6056,12 @@ msgstr "नष्ट कर दिया गया"
msgid "emailed"
msgstr "ईमेल कर दी गई"
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr ""
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -6052,12 +6074,6 @@ msgstr "श्रेणी दी जा चुकी है"
msgid "problem distribution graded"
msgstr ""
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
msgid "generated"
msgstr ""
#. Translators: This is a past-tense verb that is inserted into task progress
#. messages as {action}.
#: lms/djangoapps/instructor_task/tasks.py
@@ -7517,6 +7533,7 @@ msgid "Optional language the team uses as ISO 639-1 code."
msgstr ""
#: lms/djangoapps/teams/plugins.py
#: lms/djangoapps/teams/templates/teams/teams.html
msgid "Teams"
msgstr ""
@@ -7529,11 +7546,11 @@ msgid "course_id must be provided"
msgstr ""
#: lms/djangoapps/teams/views.py
msgid "The supplied topic id {topic_id} is not valid"
msgid "text_search and order_by cannot be provided together"
msgstr ""
#: lms/djangoapps/teams/views.py
msgid "text_search is not yet supported."
msgid "The supplied topic id {topic_id} is not valid"
msgstr ""
#. Translators: 'ordering' is a string describing a way
@@ -9269,6 +9286,10 @@ msgstr "सहायता"
msgid "Sign Out"
msgstr ""
#: common/lib/capa/capa/templates/codeinput.html
msgid "{programming_language} editor"
msgstr ""
#: common/templates/license.html
msgid "All Rights Reserved"
msgstr ""
@@ -11836,8 +11857,10 @@ msgid "Section:"
msgstr "धारा:"
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid "Problem urlname:"
msgstr "समस्या का यू आर एल दें:"
msgid ""
"To download a CSV listing student responses to a given problem, visit the "
"Data Download section of the Instructor Dashboard."
msgstr ""
#: lms/templates/courseware/legacy_instructor_dashboard.html
msgid ""
@@ -13650,6 +13673,20 @@ msgstr ""
msgid "Generate Proctored Exam Results Report"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"To generate a CSV file that lists all student answers to a given problem, "
"enter the location of the problem (from its Staff Debug Info)."
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Problem location: "
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid "Download a CSV of problem responses"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
msgid ""
"For smaller courses, click to list profile information for enrolled students"
@@ -16013,41 +16050,50 @@ msgid "This module is not enabled."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"Upon successful completion of your course, learners receive a certificate to"
" acknowledge their accomplishment. If you are a course team member with the "
"Admin role in Studio, you can configure your course certificate."
msgid "Working with Certificates"
msgstr ""
#: cms/templates/certificates.html
msgid ""
"Click {em_start}Add your first certificate{em_end} to add a certificate "
"configuration. Upload the organization logo to be used on the certificate, "
"and specify at least one signatory. You can include up to four signatories "
"for a certificate. You can also upload a signature image file for each "
"signatory. {em_start}Note:{em_end} Signature images are used only for "
"verified certificates. Optionally, specify a different course title to use "
"on your course certificate. You might want to use a different title if, for "
"example, the official course name is too long to display well on a "
"certificate."
"Specify a course title to use on the certificate if the course's official "
"title is too long to be displayed well."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"Select a course mode and click {em_start}Preview Certificate{em_end} to "
"preview the certificate that a learner in the selected enrollment track "
"would receive. When the certificate is ready for issuing, click "
"{em_start}Activate.{em_end} To stop issuing an active certificate, click "
"{em_start}Deactivate{em_end}."
"For verified certificates, specify between one and four signatories and "
"upload the associated images."
msgstr ""
#: cms/templates/certificates.html
msgid ""
" To edit the certificate configuration, hover over the top right corner of "
"the form and click {em_start}Edit{em_end}. To delete a certificate, hover "
"over the top right corner of the form and click the delete icon. In general,"
" do not delete certificates after a course has started, because some "
"certificates might already have been issued to learners."
"To edit or delete a certificate before it is activated, hover over the top "
"right corner of the form and select {em_start}Edit{em_end} or the delete "
"icon."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"To view a sample certificate, choose a course mode and select "
"{em_start}Preview Certificate{em_end}."
msgstr ""
#: cms/templates/certificates.html
msgid "Issuing Certificates to Learners"
msgstr ""
#: cms/templates/certificates.html
msgid ""
"To begin issuing certificates, a course team member with the Admin role "
"selects {em_start}Activate{em_end}. Course team members without the Admin "
"role cannot edit or delete an activated certificate."
msgstr ""
#: cms/templates/certificates.html
msgid ""
"{em_start}Do not{em_end} delete certificates after a course has started; "
"learners who have already earned certificates will no longer be able to "
"access them."
msgstr ""
#: cms/templates/certificates.html

Some files were not shown because too many files have changed in this diff Show More