diff --git a/AUTHORS b/AUTHORS index 59e6f1ab0d..1c7c99e461 100644 --- a/AUTHORS +++ b/AUTHORS @@ -225,5 +225,7 @@ Alessandro Verdura Sven Marnach Richard Moch Albert Liang -Pa Luo +Pan Luo Tyler Nickerson +Vedran Karačić +William Ono diff --git a/cms/djangoapps/contentstore/courseware_index.py b/cms/djangoapps/contentstore/courseware_index.py index f134a5993c..bcf26f3572 100644 --- a/cms/djangoapps/contentstore/courseware_index.py +++ b/cms/djangoapps/contentstore/courseware_index.py @@ -111,8 +111,7 @@ class SearchIndexerBase(object): exclude_dictionary={"id": list(exclude_items)} ) result_ids = [result["data"]["id"] for result in response["results"]] - for result_id in result_ids: - searcher.remove(cls.DOCUMENT_TYPE, result_id) + searcher.remove(cls.DOCUMENT_TYPE, result_ids) @classmethod def index(cls, modulestore, structure_key, triggered_at=None, reindex_age=REINDEX_AGE): @@ -142,7 +141,7 @@ class SearchIndexerBase(object): structure_key = cls.normalize_structure_key(structure_key) location_info = cls._get_location_info(structure_key) - # Wrap counter in dictionary - otherwise we seem to lose scope inside the embedded function `index_item` + # Wrap counter in dictionary - otherwise we seem to lose scope inside the embedded function `prepare_item_index` indexed_count = { "count": 0 } @@ -153,15 +152,20 @@ class SearchIndexerBase(object): # list - those are ready to be destroyed indexed_items = set() + # items_index is a list of all the items index dictionaries. + # it is used to collect all indexes and index them using bulk API, + # instead of per item index API call. + items_index = [] + def get_item_location(item): """ Gets the version agnostic item location """ return item.location.version_agnostic().replace(branch=None) - def index_item(item, skip_index=False, groups_usage_info=None): + def prepare_item_index(item, skip_index=False, groups_usage_info=None): """ - Add this item to the search index and indexed_items list + Add this item to the items_index and indexed_items list Arguments: item - item to add to index, its children will be processed recursively @@ -212,7 +216,7 @@ class SearchIndexerBase(object): for child_item in item.get_children(): if modulestore.has_published_version(child_item): children_groups_usage.append( - index_item( + prepare_item_index( child_item, skip_index=skip_child_index, groups_usage_info=groups_usage_info @@ -234,7 +238,7 @@ class SearchIndexerBase(object): item_index['start_date'] = item.start item_index['content_groups'] = item_content_groups if item_content_groups else None item_index.update(cls.supplemental_fields(item)) - searcher.index(cls.DOCUMENT_TYPE, item_index) + items_index.append(item_index) indexed_count["count"] += 1 return item_content_groups except Exception as err: # pylint: disable=broad-except @@ -252,7 +256,8 @@ class SearchIndexerBase(object): # Now index the content for item in structure.get_children(): - index_item(item, groups_usage_info=groups_usage_info) + prepare_item_index(item, groups_usage_info=groups_usage_info) + searcher.index(cls.DOCUMENT_TYPE, items_index) cls.remove_deleted_items(searcher, structure_key, indexed_items) except Exception as err: # pylint: disable=broad-except # broad exception so that index operation does not prevent the rest of the application from working @@ -623,7 +628,7 @@ class CourseAboutSearchIndexer(object): # Broad exception handler to protect around and report problems with indexing try: - searcher.index(cls.DISCOVERY_DOCUMENT_TYPE, course_info) + searcher.index(cls.DISCOVERY_DOCUMENT_TYPE, [course_info]) except: # pylint: disable=bare-except log.exception( "Course discovery indexing error encountered, course discovery index may be out of date %s", diff --git a/cms/djangoapps/contentstore/features/checklists.py b/cms/djangoapps/contentstore/features/checklists.py index aad13a3120..43945658fb 100644 --- a/cms/djangoapps/contentstore/features/checklists.py +++ b/cms/djangoapps/contentstore/features/checklists.py @@ -3,7 +3,6 @@ from lettuce import world, step from nose.tools import assert_true, assert_equal # pylint: disable=no-name-in-module -from terrain.steps import reload_the_page from selenium.common.exceptions import StaleElementReferenceException diff --git a/cms/djangoapps/contentstore/features/course-outline.py b/cms/djangoapps/contentstore/features/course-outline.py index 17c71b85e5..6ab7f85e81 100644 --- a/cms/djangoapps/contentstore/features/course-outline.py +++ b/cms/djangoapps/contentstore/features/course-outline.py @@ -3,7 +3,7 @@ from lettuce import world, step from common import * -from nose.tools import assert_true, assert_false, assert_equal # pylint: disable=no-name-in-module +from nose.tools import assert_true, assert_false # pylint: disable=no-name-in-module from logging import getLogger logger = getLogger(__name__) diff --git a/cms/djangoapps/contentstore/features/course-settings.py b/cms/djangoapps/contentstore/features/course-settings.py index c2aaae4989..7970a0e1f2 100644 --- a/cms/djangoapps/contentstore/features/course-settings.py +++ b/cms/djangoapps/contentstore/features/course-settings.py @@ -2,12 +2,11 @@ # pylint: disable=redefined-outer-name from lettuce import world, step -from terrain.steps import reload_the_page from selenium.webdriver.common.keys import Keys from common import type_in_codemirror, upload_file from django.conf import settings -from nose.tools import assert_true, assert_false, assert_equal # pylint: disable=no-name-in-module +from nose.tools import assert_true, assert_false # pylint: disable=no-name-in-module TEST_ROOT = settings.COMMON_TEST_DATA_ROOT diff --git a/cms/djangoapps/contentstore/features/grading.py b/cms/djangoapps/contentstore/features/grading.py index 569f39d609..bd509e6d5e 100644 --- a/cms/djangoapps/contentstore/features/grading.py +++ b/cms/djangoapps/contentstore/features/grading.py @@ -6,7 +6,7 @@ from common import * from terrain.steps import reload_the_page from selenium.common.exceptions import InvalidElementStateException from contentstore.utils import reverse_course_url -from nose.tools import assert_in, assert_not_in, assert_equal, assert_not_equal # pylint: disable=no-name-in-module +from nose.tools import assert_in, assert_equal, assert_not_equal # pylint: disable=no-name-in-module @step(u'I am viewing the grading settings') @@ -170,7 +170,7 @@ def cannot_edit_fail(_step): # try to change the grade range -- this should throw an exception try: ranges.last.value = 'Failure' - except (InvalidElementStateException): + except InvalidElementStateException: pass # We should get this exception on failing to edit the element # check to be sure that nothing has changed diff --git a/cms/djangoapps/contentstore/features/pages.py b/cms/djangoapps/contentstore/features/pages.py index ccae95b3fd..0bacc737c6 100644 --- a/cms/djangoapps/contentstore/features/pages.py +++ b/cms/djangoapps/contentstore/features/pages.py @@ -33,7 +33,7 @@ def see_a_static_page_named_foo(step, name): @step(u'I should not see any static pages$') def not_see_any_static_pages(step): pages_css = 'div.xmodule_StaticTabModule' - assert (world.is_css_not_present(pages_css, wait_time=30)) + assert world.is_css_not_present(pages_css, wait_time=30) @step(u'I "(edit|delete)" the static page$') diff --git a/cms/djangoapps/contentstore/features/transcripts.py b/cms/djangoapps/contentstore/features/transcripts.py index fa8a52d257..5f94ec90e5 100644 --- a/cms/djangoapps/contentstore/features/transcripts.py +++ b/cms/djangoapps/contentstore/features/transcripts.py @@ -205,7 +205,7 @@ def check_text_in_the_captions(_step, text): world.wait_for_present('.video.is-captions-rendered') world.wait_for(lambda _: world.css_text('.subtitles'), timeout=30) actual_text = world.css_text('.subtitles') - assert (text in actual_text) + assert text in actual_text @step('I see value "([^"]*)" in the field "([^"]*)"$') diff --git a/cms/djangoapps/contentstore/features/upload.py b/cms/djangoapps/contentstore/features/upload.py index 5ae85ddb19..a852b8e264 100644 --- a/cms/djangoapps/contentstore/features/upload.py +++ b/cms/djangoapps/contentstore/features/upload.py @@ -74,7 +74,7 @@ def check_not_there(_step, file_name): # the only file that was uploaded, our success criteria # will be that there are no files. # In the future we can refactor if necessary. - assert(world.is_css_not_present(ASSET_NAMES_CSS)) + assert world.is_css_not_present(ASSET_NAMES_CSS) @step(u'I should see the file "([^"]*)" was uploaded$') diff --git a/cms/djangoapps/contentstore/management/commands/delete_course.py b/cms/djangoapps/contentstore/management/commands/delete_course.py index 2ae3318a72..16a6c88330 100644 --- a/cms/djangoapps/contentstore/management/commands/delete_course.py +++ b/cms/djangoapps/contentstore/management/commands/delete_course.py @@ -1,6 +1,13 @@ -### -### Script for cloning a course -### +""" + Command for deleting courses + + Arguments: + arg1 (str): Course key of the course to delete + arg2 (str): 'commit' + + Returns: + none +""" from django.core.management.base import BaseCommand, CommandError from .prompt import query_yes_no from contentstore.utils import delete_course_and_groups @@ -8,27 +15,56 @@ from opaque_keys.edx.keys import CourseKey from opaque_keys import InvalidKeyError from opaque_keys.edx.locations import SlashSeparatedCourseKey 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 + """ help = '''Delete a MongoDB backed course''' def handle(self, *args, **options): - if len(args) != 1 and len(args) != 2: - raise CommandError("delete_course requires one or more arguments: |commit|") + if len(args) == 0: + raise CommandError("Arguments missing: 'org/number/run commit'") - try: - course_key = CourseKey.from_string(args[0]) - except InvalidKeyError: - course_key = SlashSeparatedCourseKey.from_deprecated_string(args[0]) + if len(args) == 1: + if args[0] == 'commit': + raise CommandError("Delete_course requires a course_key argument.") + else: + raise CommandError("Delete_course requires a commit argument at the end") + elif len(args) == 2: + try: + course_key = CourseKey.from_string(args[0]) + except InvalidKeyError: + try: + course_key = SlashSeparatedCourseKey.from_deprecated_string(args[0]) + except InvalidKeyError: + raise CommandError("Invalid course_key: '%s'. Proper syntax: 'org/number/run commit' " % args[0]) + if args[1] != 'commit': + raise CommandError("Delete_course requires a commit argument at the end") + elif len(args) > 2: + raise CommandError("Too many arguments! Expected ") - commit = False - if len(args) == 2: - commit = args[1] == 'commit' + print_out_all_courses() - if commit: - print('Actually going to delete the course from DB....') + if not modulestore().get_course(course_key): + raise CommandError("Course with '%s' key not found." % args[0]) - 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 'Actually going to delete the %s course from DB....' % args[0] + 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() diff --git a/cms/djangoapps/contentstore/management/commands/export.py b/cms/djangoapps/contentstore/management/commands/export.py index b2e36fd746..2aa2b0fdba 100644 --- a/cms/djangoapps/contentstore/management/commands/export.py +++ b/cms/djangoapps/contentstore/management/commands/export.py @@ -26,11 +26,17 @@ class Command(BaseCommand): try: course_key = CourseKey.from_string(args[0]) except InvalidKeyError: - course_key = SlashSeparatedCourseKey.from_deprecated_string(args[0]) + try: + course_key = SlashSeparatedCourseKey.from_deprecated_string(args[0]) + except InvalidKeyError: + raise CommandError("Invalid course_key: '%s'. " % args[0]) + + if not modulestore().get_course(course_key): + raise CommandError("Course with %s key not found." % args[0]) output_path = args[1] - print("Exporting course id = {0} to {1}".format(course_key, output_path)) + print "Exporting course id = {0} to {1}".format(course_key, output_path) if not output_path.endswith('/'): output_path += '/' diff --git a/cms/djangoapps/contentstore/management/commands/import.py b/cms/djangoapps/contentstore/management/commands/import.py index 8de0b33e22..870d4eb722 100644 --- a/cms/djangoapps/contentstore/management/commands/import.py +++ b/cms/djangoapps/contentstore/management/commands/import.py @@ -29,7 +29,7 @@ class Command(BaseCommand): raise CommandError("import requires at least one argument: [--nostatic] [...]") data_dir = args[0] - do_import_static = not (options.get('nostatic', False)) + do_import_static = not options.get('nostatic', False) if len(args) > 1: source_dirs = args[1:] else: diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_delete_course.py b/cms/djangoapps/contentstore/management/commands/tests/test_delete_course.py new file mode 100644 index 0000000000..3cda8e29ea --- /dev/null +++ b/cms/djangoapps/contentstore/management/commands/tests/test_delete_course.py @@ -0,0 +1,120 @@ +""" +Unittests for deleting a course in an chosen modulestore +""" + +import unittest +import mock + +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 +from xmodule.modulestore.tests.factories import CourseFactory +from xmodule.modulestore.django import modulestore + + +class TestArgParsing(unittest.TestCase): + """ + Tests for parsing arguments for the 'delete_course' management command + """ + + def setUp(self): + super(TestArgParsing, self).setUp() + + self.command = Command() + + def test_no_args(self): + """ + Testing 'delete_course' command with no arguments provided + """ + errstring = "Arguments missing: 'org/number/run commit'" + with self.assertRaisesRegexp(CommandError, errstring): + self.command.handle() + + def test_no_course_key(self): + """ + Testing 'delete_course' command with no course key provided + """ + errstring = "Delete_course requires a course_key argument." + with self.assertRaisesRegexp(CommandError, errstring): + self.command.handle("commit") + + def test_commit_argument(self): + """ + Testing 'delete_course' command without 'commit' argument + """ + errstring = "Delete_course requires a commit argument at the end" + with self.assertRaisesRegexp(CommandError, errstring): + self.command.handle("TestX/TS01/run") + + def test_invalid_course_key(self): + """ + Testing 'delete_course' command with an invalid course key argument + """ + errstring = "Invalid course_key: 'TestX/TS01'. Proper syntax: 'org/number/run commit' " + with self.assertRaisesRegexp(CommandError, errstring): + self.command.handle("TestX/TS01", "commit") + + def test_missing_commit_argument(self): + """ + Testing 'delete_course' command with misspelled 'commit' argument + """ + errstring = "Delete_course requires a commit argument at the end" + with self.assertRaisesRegexp(CommandError, errstring): + self.command.handle("TestX/TS01/run", "comit") + + def test_too_many_arguments(self): + """ + Testing 'delete_course' command with more than 2 arguments + """ + errstring = "Too many arguments! Expected " + with self.assertRaisesRegexp(CommandError, errstring): + self.command.handle("TestX/TS01/run", "commit", "invalid") + + +class DeleteCourseTest(CourseTestCase): + """ + Test for course deleting functionality of the 'delete_course' command + """ + + YESNO_PATCH_LOCATION = 'contentstore.management.commands.delete_course.query_yes_no' + + def setUp(self): + super(DeleteCourseTest, self).setUp() + + self.command = Command() + + org = 'TestX' + course_number = 'TS01' + course_run = '2015_Q1' + + # Create a course using split modulestore + self.course = CourseFactory.create( + org=org, + number=course_number, + 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") + + def test_course_deleted(self): + """ + Testing if the entered course was deleted + """ + 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) diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_export.py b/cms/djangoapps/contentstore/management/commands/tests/test_export.py index 0ed210826a..5ac8fb8d83 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_export.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_export.py @@ -7,7 +7,6 @@ import ddt from django.core.management import CommandError, call_command from tempfile import mkdtemp -from opaque_keys import InvalidKeyError from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase @@ -22,6 +21,9 @@ class TestArgParsingCourseExport(unittest.TestCase): super(TestArgParsingCourseExport, self).setUp() def test_no_args(self): + """ + Test export command with no arguments + """ errstring = "export requires two arguments: " with self.assertRaises(SystemExit) as ex: with self.assertRaisesRegexp(CommandError, errstring): @@ -57,9 +59,22 @@ class TestCourseExport(ModuleStoreTestCase): "Could not find course in {}".format(store) ) # Test `export` management command with invalid course_id - with self.assertRaises(InvalidKeyError): - call_command('export', "InvalidCourseID", self.temp_dir_1) + errstring = "Invalid course_key 'InvalidCourseID'." + with self.assertRaises(SystemExit) as ex: + with self.assertRaisesRegexp(CommandError, errstring): + call_command('export', "InvalidCourseID", self.temp_dir_1) + self.assertEqual(ex.exception.code, 1) # Test `export` management command with correct course_id for output_dir in [self.temp_dir_1, self.temp_dir_2]: call_command('export', course_id, output_dir) + + def test_course_key_not_found(self): + """ + Test export command with a valid course key that doesn't exist + """ + errstring = "Course with x/y/z key not found." + with self.assertRaises(SystemExit) as ex: + with self.assertRaisesRegexp(CommandError, errstring): + call_command('export', "x/y/z", self.temp_dir_1) + self.assertEqual(ex.exception.code, 1) diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index 1b1aaee4c9..79feeae460 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -659,7 +659,7 @@ class MiscCourseTests(ContentStoreTestCase): direct_store_items = self.store.get_items( self.course.id, revision=ModuleStoreEnum.RevisionOption.published_only ) - items_from_direct_store = [item for item in direct_store_items if (item.location == self.problem.location)] + items_from_direct_store = [item for item in direct_store_items if item.location == self.problem.location] self.assertEqual(len(items_from_direct_store), 1) self.assertFalse(getattr(items_from_direct_store[0], 'is_draft', False)) @@ -667,7 +667,7 @@ class MiscCourseTests(ContentStoreTestCase): draft_store_items = self.store.get_items( self.course.id, revision=ModuleStoreEnum.RevisionOption.draft_only ) - items_from_draft_store = [item for item in draft_store_items if (item.location == self.problem.location)] + items_from_draft_store = [item for item in draft_store_items if item.location == self.problem.location] self.assertEqual(len(items_from_draft_store), 1) # TODO the below won't work for split mongo self.assertTrue(getattr(items_from_draft_store[0], 'is_draft', False)) diff --git a/cms/djangoapps/contentstore/tests/test_courseware_index.py b/cms/djangoapps/contentstore/tests/test_courseware_index.py index 527192937b..5001712f15 100644 --- a/cms/djangoapps/contentstore/tests/test_courseware_index.py +++ b/cms/djangoapps/contentstore/tests/test_courseware_index.py @@ -871,8 +871,7 @@ class TestLibrarySearchIndexer(MixedWithOptionsTestCase): self.update_item(store, self.html_unit1) self.reindex_library(store) response = self.search() - # TODO: MockSearchEngine never updates existing item: returns 3 items here - uncomment when it's fixed - # self.assertEqual(response["total"], 2) + self.assertEqual(response["total"], 2) html_contents = [cont['html_content'] for cont in self._get_contents(response)] self.assertIn(new_data, html_contents) @@ -1167,95 +1166,91 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase): def _html_group_result(self, html_unit, content_groups): """ - Return call object with arguments and content group for html_unit. + Return object with arguments and content group for html_unit. """ - return call( - 'courseware_content', - { - 'course_name': unicode(self.course.display_name), - 'id': unicode(html_unit.location), - 'content': {'html_content': '', 'display_name': unicode(html_unit.display_name)}, - 'course': unicode(self.course.id), - 'location': [ - unicode(self.chapter.display_name), - unicode(self.sequential.display_name), - unicode(html_unit.parent.display_name) - ], - 'content_type': 'Text', - 'org': self.course.org, - 'content_groups': content_groups, - 'start_date': datetime(2015, 4, 1, 0, 0, tzinfo=tzutc()) - } - ) + return { + 'course_name': self.course.display_name, + 'id': unicode(html_unit.location), + 'content': {'html_content': '', 'display_name': html_unit.display_name}, + 'course': unicode(self.course.id), + 'location': [ + self.chapter.display_name, + self.sequential.display_name, + html_unit.parent.display_name + ], + 'content_type': 'Text', + 'org': self.course.org, + 'content_groups': content_groups, + 'start_date': datetime(2015, 4, 1, 0, 0, tzinfo=tzutc()) + } def _html_experiment_group_result(self, html_unit, content_groups): """ - Return call object with arguments and content group for html_unit. + Return object with arguments and content group for html_unit. """ - return call( - 'courseware_content', - { - 'course_name': unicode(self.course.display_name), - 'id': unicode(html_unit.location), - 'content': {'html_content': '', 'display_name': unicode(html_unit.display_name)}, - 'course': unicode(self.course.id), - 'location': [ - unicode(self.chapter.display_name), - unicode(self.sequential2.display_name), - unicode(self.vertical3.display_name) - ], - 'content_type': 'Text', - 'org': self.course.org, - 'content_groups': content_groups, - 'start_date': datetime(2015, 4, 1, 0, 0, tzinfo=tzutc()) - } - ) + return { + 'course_name': self.course.display_name, + 'id': unicode(html_unit.location), + 'content': {'html_content': '', 'display_name': html_unit.display_name}, + 'course': unicode(self.course.id), + 'location': [ + self.chapter.display_name, + self.sequential2.display_name, + self.vertical3.display_name + ], + 'content_type': 'Text', + 'org': self.course.org, + 'content_groups': content_groups, + 'start_date': datetime(2015, 4, 1, 0, 0, tzinfo=tzutc()) + } def _vertical_experiment_group_result(self, vertical, content_groups): """ - Return call object with arguments and content group for split_test vertical. + Return object with arguments and content group for split_test vertical. """ - return call( - 'courseware_content', - { - 'start_date': datetime(2015, 4, 1, 0, 0, tzinfo=tzutc()), - 'content': {'display_name': unicode(vertical.display_name)}, - 'course': unicode(self.course.id), - 'location': [ - unicode(self.chapter.display_name), - unicode(self.sequential2.display_name), - unicode(vertical.parent.display_name) - ], - 'content_type': 'Sequence', - 'content_groups': content_groups, - 'id': unicode(vertical.location), - 'course_name': unicode(self.course.display_name), - 'org': self.course.org - } - ) + return { + 'start_date': datetime(2015, 4, 1, 0, 0, tzinfo=tzutc()), + 'content': {'display_name': vertical.display_name}, + 'course': unicode(self.course.id), + 'location': [ + self.chapter.display_name, + self.sequential2.display_name, + vertical.parent.display_name + ], + 'content_type': 'Sequence', + 'content_groups': content_groups, + 'id': unicode(vertical.location), + 'course_name': self.course.display_name, + 'org': self.course.org + } def _html_nogroup_result(self, html_unit): """ - Return call object with arguments and content group set to empty array for html_unit. + Return object with arguments and content group set to empty array for html_unit. """ - return call( - 'courseware_content', - { - 'course_name': unicode(self.course.display_name), - 'id': unicode(html_unit.location), - 'content': {'html_content': '', 'display_name': unicode(html_unit.display_name)}, - 'course': unicode(self.course.id), - 'location': [ - unicode(self.chapter.display_name), - unicode(self.sequential.display_name), - unicode(html_unit.parent.display_name) - ], - 'content_type': 'Text', - 'org': self.course.org, - 'content_groups': None, - 'start_date': datetime(2015, 4, 1, 0, 0, tzinfo=tzutc()) - } - ) + return { + 'course_name': self.course.display_name, + 'id': unicode(html_unit.location), + 'content': {'html_content': '', 'display_name': html_unit.display_name}, + 'course': unicode(self.course.id), + 'location': [ + self.chapter.display_name, + self.sequential.display_name, + html_unit.parent.display_name + ], + 'content_type': 'Text', + 'org': self.course.org, + 'content_groups': None, + 'start_date': datetime(2015, 4, 1, 0, 0, tzinfo=tzutc()) + } + + def _get_index_values_from_call_args(self, mock_index): + """ + Return content values from args tuple in a mocked calls list. + """ + kall = mock_index.call_args + args, kwargs = kall # pylint: disable=unused-variable + return args[1] def reindex_course(self, store): """ kick off complete reindex of the course """ @@ -1268,7 +1263,7 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase): added_to_index = self.reindex_course(self.store) self.assertEqual(added_to_index, 16) response = self.searcher.search(field_dictionary={"course": unicode(self.course.id)}) - self.assertEqual(response["total"], 23) + self.assertEqual(response["total"], 17) group_access_content = {'group_access': {666: [1]}} @@ -1283,46 +1278,47 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase): with patch(settings.SEARCH_ENGINE + '.index') as mock_index: self.reindex_course(self.store) self.assertTrue(mock_index.called) - self.assertIn(self._html_group_result(self.html_unit1, [1]), mock_index.mock_calls) - self.assertIn(self._html_experiment_group_result(self.html_unit4, [unicode(2)]), mock_index.mock_calls) - self.assertIn(self._html_experiment_group_result(self.html_unit5, [unicode(3)]), mock_index.mock_calls) - self.assertIn(self._html_experiment_group_result(self.html_unit6, [unicode(4)]), mock_index.mock_calls) - self.assertNotIn(self._html_experiment_group_result(self.html_unit6, [unicode(5)]), mock_index.mock_calls) + indexed_content = self._get_index_values_from_call_args(mock_index) + self.assertIn(self._html_group_result(self.html_unit1, [1]), indexed_content) + self.assertIn(self._html_experiment_group_result(self.html_unit4, [unicode(2)]), indexed_content) + self.assertIn(self._html_experiment_group_result(self.html_unit5, [unicode(3)]), indexed_content) + self.assertIn(self._html_experiment_group_result(self.html_unit6, [unicode(4)]), indexed_content) + self.assertNotIn(self._html_experiment_group_result(self.html_unit6, [unicode(5)]), indexed_content) self.assertIn( self._vertical_experiment_group_result(self.condition_0_vertical, [unicode(2)]), - mock_index.mock_calls + indexed_content ) self.assertNotIn( self._vertical_experiment_group_result(self.condition_1_vertical, [unicode(2)]), - mock_index.mock_calls + indexed_content ) self.assertNotIn( self._vertical_experiment_group_result(self.condition_2_vertical, [unicode(2)]), - mock_index.mock_calls + indexed_content ) self.assertNotIn( self._vertical_experiment_group_result(self.condition_0_vertical, [unicode(3)]), - mock_index.mock_calls + indexed_content ) self.assertIn( self._vertical_experiment_group_result(self.condition_1_vertical, [unicode(3)]), - mock_index.mock_calls + indexed_content ) self.assertNotIn( self._vertical_experiment_group_result(self.condition_2_vertical, [unicode(3)]), - mock_index.mock_calls + indexed_content ) self.assertNotIn( self._vertical_experiment_group_result(self.condition_0_vertical, [unicode(4)]), - mock_index.mock_calls + indexed_content ) self.assertNotIn( self._vertical_experiment_group_result(self.condition_1_vertical, [unicode(4)]), - mock_index.mock_calls + indexed_content ) self.assertIn( self._vertical_experiment_group_result(self.condition_2_vertical, [unicode(4)]), - mock_index.mock_calls + indexed_content ) mock_index.reset_mock() @@ -1332,7 +1328,8 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase): with patch(settings.SEARCH_ENGINE + '.index') as mock_index: self.reindex_course(self.store) self.assertTrue(mock_index.called) - self.assertIn(self._html_nogroup_result(self.html_unit1), mock_index.mock_calls) + indexed_content = self._get_index_values_from_call_args(mock_index) + self.assertIn(self._html_nogroup_result(self.html_unit1), indexed_content) mock_index.reset_mock() def test_content_group_not_indexed_on_delete(self): @@ -1351,7 +1348,8 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase): with patch(settings.SEARCH_ENGINE + '.index') as mock_index: self.reindex_course(self.store) self.assertTrue(mock_index.called) - self.assertIn(self._html_group_result(self.html_unit1, [1]), mock_index.mock_calls) + indexed_content = self._get_index_values_from_call_args(mock_index) + self.assertIn(self._html_group_result(self.html_unit1, [1]), indexed_content) mock_index.reset_mock() empty_group_access = {'group_access': {}} @@ -1367,7 +1365,8 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase): with patch(settings.SEARCH_ENGINE + '.index') as mock_index: self.reindex_course(self.store) self.assertTrue(mock_index.called) - self.assertIn(self._html_nogroup_result(self.html_unit1), mock_index.mock_calls) + indexed_content = self._get_index_values_from_call_args(mock_index) + self.assertIn(self._html_nogroup_result(self.html_unit1), indexed_content) mock_index.reset_mock() def test_group_indexed_only_on_assigned_html_block(self): @@ -1383,8 +1382,9 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase): with patch(settings.SEARCH_ENGINE + '.index') as mock_index: self.reindex_course(self.store) self.assertTrue(mock_index.called) - self.assertIn(self._html_group_result(self.html_unit1, [1]), mock_index.mock_calls) - self.assertIn(self._html_nogroup_result(self.html_unit2), mock_index.mock_calls) + indexed_content = self._get_index_values_from_call_args(mock_index) + self.assertIn(self._html_group_result(self.html_unit1, [1]), indexed_content) + self.assertIn(self._html_nogroup_result(self.html_unit2), indexed_content) mock_index.reset_mock() def test_different_groups_indexed_on_assigned_html_blocks(self): @@ -1407,8 +1407,9 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase): with patch(settings.SEARCH_ENGINE + '.index') as mock_index: self.reindex_course(self.store) self.assertTrue(mock_index.called) - self.assertIn(self._html_group_result(self.html_unit1, [1]), mock_index.mock_calls) - self.assertIn(self._html_group_result(self.html_unit2, [0]), mock_index.mock_calls) + indexed_content = self._get_index_values_from_call_args(mock_index) + self.assertIn(self._html_group_result(self.html_unit1, [1]), indexed_content) + self.assertIn(self._html_group_result(self.html_unit2, [0]), indexed_content) mock_index.reset_mock() def test_different_groups_indexed_on_same_vertical_html_blocks(self): @@ -1435,8 +1436,9 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase): with patch(settings.SEARCH_ENGINE + '.index') as mock_index: self.reindex_course(self.store) self.assertTrue(mock_index.called) - self.assertIn(self._html_group_result(self.html_unit2, [1]), mock_index.mock_calls) - self.assertIn(self._html_group_result(self.html_unit3, [0]), mock_index.mock_calls) + indexed_content = self._get_index_values_from_call_args(mock_index) + self.assertIn(self._html_group_result(self.html_unit2, [1]), indexed_content) + self.assertIn(self._html_group_result(self.html_unit3, [0]), indexed_content) mock_index.reset_mock() diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py index 8e6a311f36..b65f973da2 100644 --- a/cms/djangoapps/contentstore/utils.py +++ b/cms/djangoapps/contentstore/utils.py @@ -87,7 +87,7 @@ def get_lms_link_for_item(location, preview=False): :param location: the location to jump to :param preview: True if the preview version of LMS should be returned. Default value is false. """ - assert(isinstance(location, UsageKey)) + assert isinstance(location, UsageKey) if settings.LMS_BASE is None: return None @@ -109,7 +109,7 @@ def get_lms_link_for_about_page(course_key): Returns the url to the course about page from the location tuple. """ - assert(isinstance(course_key, CourseKey)) + assert isinstance(course_key, CourseKey) if settings.FEATURES.get('ENABLE_MKTG_SITE', False): if not hasattr(settings, 'MKTG_URLS'): diff --git a/cms/djangoapps/contentstore/views/access.py b/cms/djangoapps/contentstore/views/access.py index bafb5000e1..a5348c702a 100644 --- a/cms/djangoapps/contentstore/views/access.py +++ b/cms/djangoapps/contentstore/views/access.py @@ -16,7 +16,7 @@ def get_user_role(user, course_id): :param course_id: the course_id of the course we're interested in """ # afaik, this is only used in lti - if auth.has_access(user, CourseInstructorRole(course_id)): + if auth.user_has_role(user, CourseInstructorRole(course_id)): return 'instructor' else: return 'staff' diff --git a/cms/djangoapps/contentstore/views/certificates.py b/cms/djangoapps/contentstore/views/certificates.py index 96e2f522e6..6aa898c3da 100644 --- a/cms/djangoapps/contentstore/views/certificates.py +++ b/cms/djangoapps/contentstore/views/certificates.py @@ -33,7 +33,9 @@ from django.views.decorators.http import require_http_methods from contentstore.utils import reverse_course_url from edxmako.shortcuts import render_to_response from opaque_keys.edx.keys import CourseKey, AssetKey +from eventtracking import tracker from student.auth import has_studio_write_access +from student.roles import GlobalStaff from util.db import generate_int_id, MYSQL_MAX_INT from util.json_request import JsonResponse from xmodule.modulestore import EdxJSONEncoder @@ -247,6 +249,20 @@ class CertificateManager(object): store.update_item(course, request.user.id) break + @staticmethod + def track_event(event_name, event_data): + """Track certificate configuration event. + + Arguments: + event_name (str): Name of the event to be logged. + event_data (dict): A Dictionary containing event data + Returns: + None + + """ + event_name = '.'.join(['edx', 'certificate', 'configuration', event_name]) + tracker.emit(event_name, event_data) + class Certificate(object): """ @@ -278,6 +294,9 @@ def certificate_activation_handler(request, course_key_string): POST json: is_active. update the activation state of certificate """ + # Only global staff (PMs) are able to activate/deactivate certificate configuration + if not GlobalStaff().has_user(request.user): + raise PermissionDenied() course_key = CourseKey.from_string(course_key_string) store = modulestore() try: @@ -296,6 +315,10 @@ def certificate_activation_handler(request, course_key_string): break store.update_item(course, request.user.id) + cert_event_type = 'activated' if is_active else 'deactivated' + CertificateManager.track_event(cert_event_type, { + 'course_id': unicode(course.id), + }) return HttpResponse(status=200) @@ -375,6 +398,10 @@ def certificates_list_handler(request, course_key_string): kwargs={'certificate_id': new_certificate.id} # pylint: disable=no-member ) store.update_item(course, request.user.id) + CertificateManager.track_event('created', { + 'course_id': unicode(course.id), + 'configuration_id': new_certificate.id + }) course = _get_course_and_check_access(course_key, request.user) return response else: @@ -414,15 +441,25 @@ def certificates_detail_handler(request, course_key_string, certificate_id): return JsonResponse({"error": err.message}, status=400) serialized_certificate = CertificateManager.serialize_certificate(new_certificate) + cert_event_type = 'created' if match_cert: + cert_event_type = 'modified' certificates_list[match_index] = serialized_certificate else: certificates_list.append(serialized_certificate) store.update_item(course, request.user.id) + CertificateManager.track_event(cert_event_type, { + 'course_id': unicode(course.id), + 'configuration_id': serialized_certificate["id"] + }) return JsonResponse(serialized_certificate, status=201) elif request.method == "DELETE": + # Only global staff (PMs) are able to activate/deactivate certificate configuration + if not GlobalStaff().has_user(request.user): + raise PermissionDenied() + if not match_cert: return JsonResponse(status=404) CertificateManager.remove_certificate( @@ -431,6 +468,10 @@ def certificates_detail_handler(request, course_key_string, certificate_id): course=course, certificate_id=certificate_id ) + CertificateManager.track_event('deleted', { + 'course_id': unicode(course.id), + 'configuration_id': certificate_id + }) return JsonResponse(status=204) diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index 502af763f8..522730034b 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -662,7 +662,7 @@ def _create_or_rerun_course(request): Returns the destination course_key and overriding fields for the new course. Raises DuplicateCourseError and InvalidKeyError """ - if not auth.has_access(request.user, CourseCreatorRole()): + if not auth.user_has_role(request.user, CourseCreatorRole()): raise PermissionDenied() try: diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py index b212ecc216..414d61908b 100644 --- a/cms/djangoapps/contentstore/views/item.py +++ b/cms/djangoapps/contentstore/views/item.py @@ -242,7 +242,7 @@ def xblock_view_handler(request, usage_key_string, view_name): log.debug("Unable to render %s for %r", view_name, xblock, exc_info=True) fragment = Fragment(render_to_string('html_error.html', {'message': str(exc)})) - elif view_name in (PREVIEW_VIEWS + container_views): + elif view_name in PREVIEW_VIEWS + container_views: is_pages_view = view_name == STUDENT_VIEW # Only the "Pages" view uses student view in Studio can_edit = has_studio_write_access(request.user, usage_key.course_key) diff --git a/cms/djangoapps/contentstore/views/library.py b/cms/djangoapps/contentstore/views/library.py index 7d0fcf63ba..1323aa4f09 100644 --- a/cms/djangoapps/contentstore/views/library.py +++ b/cms/djangoapps/contentstore/views/library.py @@ -31,7 +31,6 @@ from student.auth import ( STUDIO_VIEW_USERS, STUDIO_EDIT_ROLES, get_user_permissions, has_studio_read_access, has_studio_write_access ) from student.roles import CourseInstructorRole, CourseStaffRole, LibraryUserRole -from student import auth from util.json_request import expect_json, JsonResponse, JsonResponseBadRequest __all__ = ['library_handler', 'manage_library_users'] diff --git a/cms/djangoapps/contentstore/views/preview.py b/cms/djangoapps/contentstore/views/preview.py index d23c4476e1..6e5d6dc768 100644 --- a/cms/djangoapps/contentstore/views/preview.py +++ b/cms/djangoapps/contentstore/views/preview.py @@ -19,7 +19,6 @@ from xmodule.services import SettingsService from xmodule.modulestore.django import modulestore, ModuleI18nService from xmodule.mixin import wrap_with_license from opaque_keys.edx.keys import UsageKey -from opaque_keys.edx.locator import LibraryUsageLocator from xmodule.x_module import ModuleSystem from xblock.runtime import KvsFieldData from xblock.django.request import webob_to_django_response, django_to_webob_request diff --git a/cms/djangoapps/contentstore/views/tabs.py b/cms/djangoapps/contentstore/views/tabs.py index 9a2d173f03..f79d4d0721 100644 --- a/cms/djangoapps/contentstore/views/tabs.py +++ b/cms/djangoapps/contentstore/views/tabs.py @@ -5,7 +5,6 @@ from student.auth import has_course_author_access from util.json_request import expect_json, JsonResponse from django.http import HttpResponseNotFound -from django.conf import settings from django.contrib.auth.decorators import login_required from django.core.exceptions import PermissionDenied from django.views.decorators.csrf import ensure_csrf_cookie diff --git a/cms/djangoapps/contentstore/views/tests/test_certificates.py b/cms/djangoapps/contentstore/views/tests/test_certificates.py index ec3a8a8f87..72f80e3f61 100644 --- a/cms/djangoapps/contentstore/views/tests/test_certificates.py +++ b/cms/djangoapps/contentstore/views/tests/test_certificates.py @@ -20,10 +20,12 @@ from xmodule.contentstore.django import contentstore from xmodule.contentstore.content import StaticContent from xmodule.exceptions import NotFoundError from student.models import CourseEnrollment +from student.roles import CourseInstructorRole, CourseStaffRole from student.tests.factories import UserFactory from contentstore.views.certificates import CertificateManager from django.test.utils import override_settings from contentstore.utils import get_lms_link_for_certificate_web_view +from util.testing import EventTestMixin FEATURES_WITH_CERTS_ENABLED = settings.FEATURES.copy() FEATURES_WITH_CERTS_ENABLED['CERTIFICATES_HTML_VIEW'] = True @@ -194,7 +196,7 @@ class CertificatesBaseTestCase(object): # pylint: disable=no-member @override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED) -class CertificatesListHandlerTestCase(CourseTestCase, CertificatesBaseTestCase, HelperMethods): +class CertificatesListHandlerTestCase(EventTestMixin, CourseTestCase, CertificatesBaseTestCase, HelperMethods): """ Test cases for certificates_list_handler. """ @@ -202,7 +204,7 @@ class CertificatesListHandlerTestCase(CourseTestCase, CertificatesBaseTestCase, """ Set up CertificatesListHandlerTestCase. """ - super(CertificatesListHandlerTestCase, self).setUp() + super(CertificatesListHandlerTestCase, self).setUp('contentstore.views.certificates.tracker') def _url(self): """ @@ -229,8 +231,13 @@ class CertificatesListHandlerTestCase(CourseTestCase, CertificatesBaseTestCase, self.assertEqual(response.status_code, 201) self.assertIn("Location", response) content = json.loads(response.content) - self._remove_ids(content) # pylint: disable=unused-variable + certificate_id = self._remove_ids(content) # pylint: disable=unused-variable self.assertEqual(content, expected) + self.assert_event_emitted( + 'edx.certificate.configuration.created', + course_id=unicode(self.course.id), + configuration_id=certificate_id, + ) def test_cannot_create_certificate_if_user_has_no_write_permissions(self): """ @@ -347,13 +354,19 @@ class CertificatesListHandlerTestCase(CourseTestCase, CertificatesBaseTestCase, @ddt.ddt @override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED) -class CertificatesDetailHandlerTestCase(CourseTestCase, CertificatesBaseTestCase, HelperMethods): +class CertificatesDetailHandlerTestCase(EventTestMixin, CourseTestCase, CertificatesBaseTestCase, HelperMethods): """ Test cases for CertificatesDetailHandlerTestCase. """ _id = 0 + def setUp(self): # pylint: disable=arguments-differ + """ + Set up CertificatesDetailHandlerTestCase. + """ + super(CertificatesDetailHandlerTestCase, self).setUp('contentstore.views.certificates.tracker') + def _url(self, cid=-1): """ Return url for the handler. @@ -388,6 +401,11 @@ class CertificatesDetailHandlerTestCase(CourseTestCase, CertificatesBaseTestCase ) content = json.loads(response.content) self.assertEqual(content, expected) + self.assert_event_emitted( + 'edx.certificate.configuration.created', + course_id=unicode(self.course.id), + configuration_id=666, + ) def test_can_edit_certificate(self): """ @@ -415,6 +433,11 @@ class CertificatesDetailHandlerTestCase(CourseTestCase, CertificatesBaseTestCase ) content = json.loads(response.content) self.assertEqual(content, expected) + self.assert_event_emitted( + 'edx.certificate.configuration.modified', + course_id=unicode(self.course.id), + configuration_id=1, + ) self.reload_course() # Verify that certificate is properly updated in the course. @@ -440,6 +463,11 @@ class CertificatesDetailHandlerTestCase(CourseTestCase, CertificatesBaseTestCase HTTP_X_REQUESTED_WITH="XMLHttpRequest", ) self.assertEqual(response.status_code, 204) + self.assert_event_emitted( + 'edx.certificate.configuration.deleted', + course_id=unicode(self.course.id), + configuration_id='1', + ) self.reload_course() # Verify that certificates are properly updated in the course. certificates = self.course.certificates['certificates'] @@ -464,6 +492,23 @@ class CertificatesDetailHandlerTestCase(CourseTestCase, CertificatesBaseTestCase ) self.assertEqual(response.status_code, 403) + def test_delete_certificate_without_global_staff_permissions(self): + """ + Tests certificate deletion without global staff permission on course. + """ + self._add_course_certificates(count=2, signatory_count=1) + user = UserFactory() + for role in [CourseInstructorRole, CourseStaffRole]: + role(self.course.id).add_users(user) + self.client.login(username=user.username, password='test') + response = self.client.delete( + self._url(cid=1), + content_type="application/json", + HTTP_ACCEPT="application/json", + HTTP_X_REQUESTED_WITH="XMLHttpRequest", + ) + self.assertEqual(response.status_code, 403) + def test_delete_non_existing_certificate(self): """ Try to delete a non existing certificate. It should return status code 404 Not found. @@ -553,6 +598,11 @@ class CertificatesDetailHandlerTestCase(CourseTestCase, CertificatesBaseTestCase course = self.store.get_course(self.course.id) certificates = course.certificates['certificates'] self.assertEqual(certificates[0].get('is_active'), is_active) + cert_event_type = 'activated' if is_active else 'deactivated' + self.assert_event_emitted( + '.'.join(['edx.certificate.configuration', cert_event_type]), + course_id=unicode(self.course.id), + ) @ddt.data(True, False) def test_certificate_activation_without_write_permissions(self, activate): @@ -573,6 +623,27 @@ class CertificatesDetailHandlerTestCase(CourseTestCase, CertificatesBaseTestCase ) self.assertEquals(response.status_code, 403) + @ddt.data(True, False) + def test_certificate_activation_without_global_staff_permissions(self, activate): + """ + Tests certificate Activate and Deactivate should not be allowed if user + does not have global staff permissions on course. + """ + test_url = reverse_course_url('certificates.certificate_activation_handler', self.course.id) + self._add_course_certificates(count=1, signatory_count=2) + user = UserFactory() + for role in [CourseInstructorRole, CourseStaffRole]: + role(self.course.id).add_users(user) + self.client.login(username=user.username, password='test') + response = self.client.post( + test_url, + data=json.dumps({"is_active": activate}), + content_type="application/json", + HTTP_ACCEPT="application/json", + HTTP_X_REQUESTED_WITH="XMLHttpRequest" + ) + self.assertEquals(response.status_code, 403) + def test_certificate_activation_failure(self): """ Certificate activation should fail when user has not read access to course then permission denied exception diff --git a/cms/djangoapps/contentstore/views/tests/test_user.py b/cms/djangoapps/contentstore/views/tests/test_user.py index ce99a266ef..725858e44d 100644 --- a/cms/djangoapps/contentstore/views/tests/test_user.py +++ b/cms/djangoapps/contentstore/views/tests/test_user.py @@ -76,8 +76,8 @@ class UsersTestCase(CourseTestCase): # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) # no content: should not be in any roles - self.assertFalse(auth.has_access(ext_user, CourseStaffRole(self.course.id))) - self.assertFalse(auth.has_access(ext_user, CourseInstructorRole(self.course.id))) + self.assertFalse(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) + self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) self.assert_not_enrolled() def test_detail_post_staff(self): @@ -90,8 +90,8 @@ class UsersTestCase(CourseTestCase): self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) - self.assertTrue(auth.has_access(ext_user, CourseStaffRole(self.course.id))) - self.assertFalse(auth.has_access(ext_user, CourseInstructorRole(self.course.id))) + self.assertTrue(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) + self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) self.assert_enrolled() def test_detail_post_staff_other_inst(self): @@ -106,12 +106,12 @@ class UsersTestCase(CourseTestCase): self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) - self.assertTrue(auth.has_access(ext_user, CourseStaffRole(self.course.id))) - self.assertFalse(auth.has_access(ext_user, CourseInstructorRole(self.course.id))) + self.assertTrue(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) + self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) self.assert_enrolled() # check that other user is unchanged user = User.objects.get(email=self.user.email) - self.assertTrue(auth.has_access(user, CourseInstructorRole(self.course.id))) + self.assertTrue(auth.user_has_role(user, CourseInstructorRole(self.course.id))) self.assertFalse(CourseStaffRole(self.course.id).has_user(user)) def test_detail_post_instructor(self): @@ -124,7 +124,7 @@ class UsersTestCase(CourseTestCase): self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) - self.assertTrue(auth.has_access(ext_user, CourseInstructorRole(self.course.id))) + self.assertTrue(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) self.assertFalse(CourseStaffRole(self.course.id).has_user(ext_user)) self.assert_enrolled() @@ -149,8 +149,8 @@ class UsersTestCase(CourseTestCase): self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) - self.assertTrue(auth.has_access(ext_user, CourseStaffRole(self.course.id))) - self.assertFalse(auth.has_access(ext_user, CourseInstructorRole(self.course.id))) + self.assertTrue(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) + self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) self.assert_enrolled() def test_detail_delete_staff(self): @@ -163,7 +163,7 @@ class UsersTestCase(CourseTestCase): self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) - self.assertFalse(auth.has_access(ext_user, CourseStaffRole(self.course.id))) + self.assertFalse(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) def test_detail_delete_instructor(self): auth.add_users(self.user, CourseInstructorRole(self.course.id), self.ext_user, self.user) @@ -175,7 +175,7 @@ class UsersTestCase(CourseTestCase): self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) - self.assertFalse(auth.has_access(ext_user, CourseInstructorRole(self.course.id))) + self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) def test_delete_last_instructor(self): auth.add_users(self.user, CourseInstructorRole(self.course.id), self.ext_user) @@ -189,7 +189,7 @@ class UsersTestCase(CourseTestCase): self.assertIn("error", result) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) - self.assertTrue(auth.has_access(ext_user, CourseInstructorRole(self.course.id))) + self.assertTrue(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) def test_post_last_instructor(self): auth.add_users(self.user, CourseInstructorRole(self.course.id), self.ext_user) @@ -204,7 +204,7 @@ class UsersTestCase(CourseTestCase): self.assertIn("error", result) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) - self.assertTrue(auth.has_access(ext_user, CourseInstructorRole(self.course.id))) + self.assertTrue(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) def test_permission_denied_self(self): auth.add_users(self.user, CourseStaffRole(self.course.id), self.user) @@ -247,7 +247,7 @@ class UsersTestCase(CourseTestCase): self.assertEqual(resp.status_code, 204) # reload user from DB user = User.objects.get(email=self.user.email) - self.assertFalse(auth.has_access(user, CourseStaffRole(self.course.id))) + self.assertFalse(auth.user_has_role(user, CourseStaffRole(self.course.id))) def test_staff_cannot_delete_other(self): auth.add_users(self.user, CourseStaffRole(self.course.id), self.user, self.ext_user) @@ -260,7 +260,7 @@ class UsersTestCase(CourseTestCase): self.assertIn("error", result) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) - self.assertTrue(auth.has_access(ext_user, CourseStaffRole(self.course.id))) + self.assertTrue(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) def test_user_not_initially_enrolled(self): # Verify that ext_user is not enrolled in the new course before being added as a staff member. diff --git a/cms/djangoapps/course_creators/tests/test_admin.py b/cms/djangoapps/course_creators/tests/test_admin.py index 47131cb198..059dbc3cb6 100644 --- a/cms/djangoapps/course_creators/tests/test_admin.py +++ b/cms/djangoapps/course_creators/tests/test_admin.py @@ -56,7 +56,7 @@ class CourseCreatorAdminTest(TestCase): def change_state_and_verify_email(state, is_creator): """ Changes user state, verifies creator status, and verifies e-mail is sent based on transition """ self._change_state(state) - self.assertEqual(is_creator, auth.has_access(self.user, CourseCreatorRole())) + self.assertEqual(is_creator, auth.user_has_role(self.user, CourseCreatorRole())) context = {'studio_request_email': self.studio_request_email} if state == CourseCreator.GRANTED: @@ -74,7 +74,7 @@ class CourseCreatorAdminTest(TestCase): with mock.patch.dict('django.conf.settings.FEATURES', self.enable_creator_group_patch): # User is initially unrequested. - self.assertFalse(auth.has_access(self.user, CourseCreatorRole())) + self.assertFalse(auth.user_has_role(self.user, CourseCreatorRole())) change_state_and_verify_email(CourseCreator.GRANTED, True) diff --git a/cms/djangoapps/course_creators/tests/test_views.py b/cms/djangoapps/course_creators/tests/test_views.py index d6b96bd373..fdca3b8d56 100644 --- a/cms/djangoapps/course_creators/tests/test_views.py +++ b/cms/djangoapps/course_creators/tests/test_views.py @@ -50,7 +50,7 @@ class CourseCreatorView(TestCase): def test_add_granted(self): with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): # Calling add_user_with_status_granted impacts is_user_in_course_group_role. - self.assertFalse(auth.has_access(self.user, CourseCreatorRole())) + self.assertFalse(auth.user_has_role(self.user, CourseCreatorRole())) add_user_with_status_granted(self.admin, self.user) self.assertEqual('granted', get_course_creator_status(self.user)) @@ -59,15 +59,15 @@ class CourseCreatorView(TestCase): add_user_with_status_unrequested(self.user) self.assertEqual('granted', get_course_creator_status(self.user)) - self.assertTrue(auth.has_access(self.user, CourseCreatorRole())) + self.assertTrue(auth.user_has_role(self.user, CourseCreatorRole())) def test_update_creator_group(self): with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): - self.assertFalse(auth.has_access(self.user, CourseCreatorRole())) + self.assertFalse(auth.user_has_role(self.user, CourseCreatorRole())) update_course_creator_group(self.admin, self.user, True) - self.assertTrue(auth.has_access(self.user, CourseCreatorRole())) + self.assertTrue(auth.user_has_role(self.user, CourseCreatorRole())) update_course_creator_group(self.admin, self.user, False) - self.assertFalse(auth.has_access(self.user, CourseCreatorRole())) + self.assertFalse(auth.user_has_role(self.user, CourseCreatorRole())) def test_user_requested_access(self): add_user_with_status_unrequested(self.user) diff --git a/cms/envs/acceptance.py b/cms/envs/acceptance.py index 80a00b0e10..a97c04792f 100644 --- a/cms/envs/acceptance.py +++ b/cms/envs/acceptance.py @@ -118,8 +118,8 @@ except ImportError: pass # Point the URL used to test YouTube availability to our stub YouTube server -YOUTUBE['API'] = "127.0.0.1:{0}/get_youtube_api/".format(YOUTUBE_PORT) -YOUTUBE['TEST_URL'] = "127.0.0.1:{0}/test_youtube/".format(YOUTUBE_PORT) +YOUTUBE['API'] = "http://127.0.0.1:{0}/get_youtube_api/".format(YOUTUBE_PORT) +YOUTUBE['METADATA_URL'] = "http://127.0.0.1:{0}/test_youtube/".format(YOUTUBE_PORT) YOUTUBE['TEXT_API']['url'] = "127.0.0.1:{0}/test_transcripts_youtube/".format(YOUTUBE_PORT) # Generate a random UUID so that different runs of acceptance tests don't break each other diff --git a/cms/envs/aws.py b/cms/envs/aws.py index 85396530fe..fdfaf9cca8 100644 --- a/cms/envs/aws.py +++ b/cms/envs/aws.py @@ -348,3 +348,4 @@ if FEATURES['ENABLE_COURSEWARE_INDEX'] or FEATURES['ENABLE_LIBRARY_INDEX']: XBLOCK_SETTINGS = ENV_TOKENS.get('XBLOCK_SETTINGS', {}) XBLOCK_SETTINGS.setdefault("VideoDescriptor", {})["licensing_enabled"] = FEATURES.get("LICENSING", False) +XBLOCK_SETTINGS.setdefault("VideoModule", {})['YOUTUBE_API_KEY'] = AUTH_TOKENS.get('YOUTUBE_API_KEY', YOUTUBE_API_KEY) diff --git a/cms/envs/bok_choy.env.json b/cms/envs/bok_choy.env.json index 3d73b109cb..d4a648394e 100644 --- a/cms/envs/bok_choy.env.json +++ b/cms/envs/bok_choy.env.json @@ -70,7 +70,6 @@ "CUSTOM_COURSE_URLS": true }, "ENABLE_DISCUSSION_SERVICE": true, - "ENABLE_INSTRUCTOR_ANALYTICS": true, "ENABLE_S3_GRADE_DOWNLOADS": true, "ENTRANCE_EXAMS": true, "MILESTONES_APP": true, diff --git a/cms/envs/bok_choy.py b/cms/envs/bok_choy.py index 84916debe9..51a4a5179b 100644 --- a/cms/envs/bok_choy.py +++ b/cms/envs/bok_choy.py @@ -1,9 +1,9 @@ """ -Settings for Bok Choy tests that are used for running CMS and LMS. +Settings for Bok Choy tests that are used when running Studio. Bok Choy uses two different settings files: 1. test_static_optimized is used when invoking collectstatic -2. bok_choy is used when running CMS and LMS +2. bok_choy is used when running the tests Note: it isn't possible to have a single settings file, because Django doesn't support both generating static assets to a directory and also serving static @@ -103,8 +103,8 @@ FEATURES['ENTRANCE_EXAMS'] = True # Point the URL used to test YouTube availability to our stub YouTube server YOUTUBE_PORT = 9080 -YOUTUBE['API'] = "127.0.0.1:{0}/get_youtube_api/".format(YOUTUBE_PORT) -YOUTUBE['TEST_URL'] = "127.0.0.1:{0}/test_youtube/".format(YOUTUBE_PORT) +YOUTUBE['API'] = "http://127.0.0.1:{0}/get_youtube_api/".format(YOUTUBE_PORT) +YOUTUBE['METADATA_URL'] = "http://127.0.0.1:{0}/test_youtube/".format(YOUTUBE_PORT) YOUTUBE['TEXT_API']['url'] = "127.0.0.1:{0}/test_transcripts_youtube/".format(YOUTUBE_PORT) FEATURES['ENABLE_COURSEWARE_INDEX'] = True diff --git a/cms/envs/common.py b/cms/envs/common.py index a683dce912..8ca08aedcd 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -44,7 +44,7 @@ from lms.envs.common import ( PROFILE_IMAGE_SECRET_KEY, PROFILE_IMAGE_MIN_BYTES, PROFILE_IMAGE_MAX_BYTES, # The following setting is included as it is used to check whether to # display credit eligibility table on the CMS or not. - ENABLE_CREDIT_ELIGIBILITY + ENABLE_CREDIT_ELIGIBILITY, YOUTUBE_API_KEY ) from path import path from warnings import simplefilter @@ -455,7 +455,7 @@ MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' EMBARGO_SITE_REDIRECT_URL = None ############################### Pipeline ####################################### -STATICFILES_STORAGE = 'cms.lib.django_require.staticstorage.OptimizedCachedRequireJsStorage' +STATICFILES_STORAGE = 'openedx.core.lib.django_require.staticstorage.OptimizedCachedRequireJsStorage' from openedx.core.lib.rooted_paths import rooted_glob @@ -573,7 +573,7 @@ REQUIRE_BASE_URL = "./" # A sensible value would be 'app.build.js'. Leave blank to use the built-in default build profile. # Set to False to disable running the default profile (e.g. if only using it to build Standalone # Modules) -REQUIRE_BUILD_PROFILE = "build.js" +REQUIRE_BUILD_PROFILE = "cms/js/build.js" # The name of the require.js script used by your project, relative to REQUIRE_BASE_URL. REQUIRE_JS = "js/vendor/require.js" @@ -592,6 +592,8 @@ REQUIRE_EXCLUDE = ("build.txt",) # It can also be a path to a custom class that subclasses require.environments.Environment and defines some "args" function that returns a list with the command arguments to execute. REQUIRE_ENVIRONMENT = "node" +################################# TENDER ###################################### + # If you want to enable Tender integration (http://tenderapp.com/), # put in the subdomain where Tender hosts tender_widget.js. For example, # if you want to use the URL https://example.tenderapp.com/tender_widget.js, @@ -652,10 +654,10 @@ CELERY_QUEUES = { YOUTUBE = { # YouTube JavaScript API - 'API': 'www.youtube.com/iframe_api', + 'API': 'https://www.youtube.com/iframe_api', - # URL to test YouTube availability - 'TEST_URL': 'gdata.youtube.com/feeds/api/videos/', + # URL to get YouTube metadata + 'METADATA_URL': 'https://www.googleapis.com/youtube/v3/videos', # Current youtube api for requesting transcripts. # For example: http://video.google.com/timedtext?lang=en&v=j_jEn79vS3g. @@ -994,6 +996,9 @@ ELASTIC_FIELD_MAPPINGS = { XBLOCK_SETTINGS = { "VideoDescriptor": { "licensing_enabled": FEATURES.get("LICENSING", False) + }, + 'VideoModule': { + 'YOUTUBE_API_KEY': YOUTUBE_API_KEY } } diff --git a/cms/envs/devstack_optimized.py b/cms/envs/devstack_optimized.py index 5694a96ff1..7e1cc2c792 100644 --- a/cms/envs/devstack_optimized.py +++ b/cms/envs/devstack_optimized.py @@ -29,6 +29,9 @@ TEST_ROOT = REPO_ROOT / "test_root" # pylint: disable=no-value-for-parameter # Enable debug so that static assets are served by Django DEBUG = True +# Set REQUIRE_DEBUG to false so that it behaves like production +REQUIRE_DEBUG = False + # Serve static files at /static directly from the staticfiles directory under test root. # Note: optimized files for testing are generated with settings from test_static_optimized STATIC_URL = "/static/" diff --git a/cms/envs/test_static_optimized.py b/cms/envs/test_static_optimized.py index ae5d91f521..9d7a8fc63d 100644 --- a/cms/envs/test_static_optimized.py +++ b/cms/envs/test_static_optimized.py @@ -33,3 +33,4 @@ STATIC_ROOT = (TEST_ROOT / "staticfiles" / "cms").abspath() # 1. Uglify is by far the slowest part of the build process # 2. Having full source code makes debugging tests easier for developers os.environ['REQUIRE_BUILD_PROFILE_OPTIMIZE'] = 'none' +PIPELINE_JS_COMPRESSOR = None diff --git a/cms/static/build.js b/cms/static/cms/js/build.js similarity index 94% rename from cms/static/build.js rename to cms/static/cms/js/build.js index 933041abe5..dc9abfdc5b 100644 --- a/cms/static/build.js +++ b/cms/static/cms/js/build.js @@ -1,19 +1,21 @@ (function () { 'use strict'; + var commonLibrariesPath = 'common/js/common_libraries'; + var getModule = function (moduleName, excludeCommonDeps) { var module = { name: moduleName }; if (excludeCommonDeps) { - module.exclude = ['js/factories/common_deps']; + module.exclude = [commonLibrariesPath]; } return module; }; var getModulesList = function (modules) { - var result = [getModule('js/factories/common_deps')]; + var result = [getModule(commonLibrariesPath)]; return result.concat(modules.map(function (moduleName) { return getModule(moduleName, true); })); @@ -84,6 +86,17 @@ 'tender': 'empty:', 'youtube': 'empty:' }, + + /** + * Inline requireJS text templates. + */ + inlineText: true, + + /** + * Stub out requireJS text in the optimized file, but leave available for non-optimized development use. + */ + stubModules: ["text"], + /** * If shim config is used in the app during runtime, duplicate the config * here. Necessary if shim config is used, so that the shim's dependencies diff --git a/cms/static/require-config.js b/cms/static/cms/js/require-config.js similarity index 100% rename from cms/static/require-config.js rename to cms/static/cms/js/require-config.js diff --git a/cms/static/coffee/src/views/tabs.coffee b/cms/static/coffee/src/views/tabs.coffee index 84e64311dc..c4c0388192 100644 --- a/cms/static/coffee/src/views/tabs.coffee +++ b/cms/static/coffee/src/views/tabs.coffee @@ -89,7 +89,9 @@ define ["jquery", "jquery.ui", "backbone", "js/views/feedback_prompt", "js/views editor.$el.addClass('new') setTimeout(=> editor.$el.removeClass('new') - , 500) + , 1000) + $('html, body').animate {scrollTop: $('.new-component-item').offset().top}, 500 + editor.createItem( @model.get('id'), diff --git a/cms/static/fonts/OpenSans/OpenSans-Bold-webfont.eot b/cms/static/fonts/OpenSans/OpenSans-Bold-webfont.eot deleted file mode 100755 index 5b6e0e6f19..0000000000 Binary files a/cms/static/fonts/OpenSans/OpenSans-Bold-webfont.eot and /dev/null differ diff --git a/cms/static/fonts/OpenSans/OpenSans-Bold-webfont.svg b/cms/static/fonts/OpenSans/OpenSans-Bold-webfont.svg deleted file mode 100755 index ff239cf156..0000000000 --- a/cms/static/fonts/OpenSans/OpenSans-Bold-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cms/static/fonts/OpenSans/OpenSans-Bold-webfont.woff2 b/cms/static/fonts/OpenSans/OpenSans-Bold-webfont.woff2 new file mode 100644 index 0000000000..f8eb6b3b1a Binary files /dev/null and b/cms/static/fonts/OpenSans/OpenSans-Bold-webfont.woff2 differ diff --git a/cms/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.eot b/cms/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.eot deleted file mode 100755 index b5e5e7cc3a..0000000000 Binary files a/cms/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.eot and /dev/null differ diff --git a/cms/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.svg b/cms/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.svg deleted file mode 100755 index f3c1273878..0000000000 --- a/cms/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cms/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.woff2 b/cms/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.woff2 new file mode 100644 index 0000000000..b0efa9aa5f Binary files /dev/null and b/cms/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.woff2 differ diff --git a/cms/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.ttf b/cms/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.ttf deleted file mode 100755 index d33fc355fb..0000000000 Binary files a/cms/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.ttf and /dev/null differ diff --git a/cms/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.ttf b/cms/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.ttf deleted file mode 100755 index c60cff6e0d..0000000000 Binary files a/cms/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.ttf and /dev/null differ diff --git a/cms/static/fonts/OpenSans/OpenSans-Italic-webfont.eot b/cms/static/fonts/OpenSans/OpenSans-Italic-webfont.eot deleted file mode 100755 index 54fd29dc25..0000000000 Binary files a/cms/static/fonts/OpenSans/OpenSans-Italic-webfont.eot and /dev/null differ diff --git a/cms/static/fonts/OpenSans/OpenSans-Italic-webfont.svg b/cms/static/fonts/OpenSans/OpenSans-Italic-webfont.svg deleted file mode 100755 index ab4bb7e1bb..0000000000 --- a/cms/static/fonts/OpenSans/OpenSans-Italic-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cms/static/fonts/OpenSans/OpenSans-Italic-webfont.woff2 b/cms/static/fonts/OpenSans/OpenSans-Italic-webfont.woff2 new file mode 100644 index 0000000000..f465471d57 Binary files /dev/null and b/cms/static/fonts/OpenSans/OpenSans-Italic-webfont.woff2 differ diff --git a/cms/static/fonts/OpenSans/OpenSans-Light-webfont.eot b/cms/static/fonts/OpenSans/OpenSans-Light-webfont.eot deleted file mode 100755 index ea950e622f..0000000000 Binary files a/cms/static/fonts/OpenSans/OpenSans-Light-webfont.eot and /dev/null differ diff --git a/cms/static/fonts/OpenSans/OpenSans-Light-webfont.svg b/cms/static/fonts/OpenSans/OpenSans-Light-webfont.svg deleted file mode 100755 index a36a5b7ee7..0000000000 --- a/cms/static/fonts/OpenSans/OpenSans-Light-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cms/static/fonts/OpenSans/OpenSans-Light-webfont.woff2 b/cms/static/fonts/OpenSans/OpenSans-Light-webfont.woff2 new file mode 100644 index 0000000000..1396b76299 Binary files /dev/null and b/cms/static/fonts/OpenSans/OpenSans-Light-webfont.woff2 differ diff --git a/cms/static/fonts/OpenSans/OpenSans-LightItalic-webfont.eot b/cms/static/fonts/OpenSans/OpenSans-LightItalic-webfont.eot deleted file mode 100755 index fdacf6e4e1..0000000000 Binary files a/cms/static/fonts/OpenSans/OpenSans-LightItalic-webfont.eot and /dev/null differ diff --git a/cms/static/fonts/OpenSans/OpenSans-LightItalic-webfont.svg b/cms/static/fonts/OpenSans/OpenSans-LightItalic-webfont.svg deleted file mode 100755 index 8cf6f52132..0000000000 --- a/cms/static/fonts/OpenSans/OpenSans-LightItalic-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cms/static/fonts/OpenSans/OpenSans-LightItalic-webfont.woff2 b/cms/static/fonts/OpenSans/OpenSans-LightItalic-webfont.woff2 new file mode 100644 index 0000000000..ef68939910 Binary files /dev/null and b/cms/static/fonts/OpenSans/OpenSans-LightItalic-webfont.woff2 differ diff --git a/cms/static/fonts/OpenSans/OpenSans-Regular-webfont.eot b/cms/static/fonts/OpenSans/OpenSans-Regular-webfont.eot deleted file mode 100755 index 3953513ecd..0000000000 Binary files a/cms/static/fonts/OpenSans/OpenSans-Regular-webfont.eot and /dev/null differ diff --git a/cms/static/fonts/OpenSans/OpenSans-Regular-webfont.svg b/cms/static/fonts/OpenSans/OpenSans-Regular-webfont.svg deleted file mode 100755 index a169e01ae8..0000000000 --- a/cms/static/fonts/OpenSans/OpenSans-Regular-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cms/static/fonts/OpenSans/OpenSans-Regular-webfont.woff2 b/cms/static/fonts/OpenSans/OpenSans-Regular-webfont.woff2 new file mode 100644 index 0000000000..e36e99b143 Binary files /dev/null and b/cms/static/fonts/OpenSans/OpenSans-Regular-webfont.woff2 differ diff --git a/cms/static/fonts/OpenSans/OpenSans-Semibold-webfont.eot b/cms/static/fonts/OpenSans/OpenSans-Semibold-webfont.eot deleted file mode 100755 index cfc3dd7b42..0000000000 Binary files a/cms/static/fonts/OpenSans/OpenSans-Semibold-webfont.eot and /dev/null differ diff --git a/cms/static/fonts/OpenSans/OpenSans-Semibold-webfont.svg b/cms/static/fonts/OpenSans/OpenSans-Semibold-webfont.svg deleted file mode 100755 index 2704ab4431..0000000000 --- a/cms/static/fonts/OpenSans/OpenSans-Semibold-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cms/static/fonts/OpenSans/OpenSans-Semibold-webfont.woff2 b/cms/static/fonts/OpenSans/OpenSans-Semibold-webfont.woff2 new file mode 100644 index 0000000000..21384febe4 Binary files /dev/null and b/cms/static/fonts/OpenSans/OpenSans-Semibold-webfont.woff2 differ diff --git a/cms/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.eot b/cms/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.eot deleted file mode 100755 index 635848ce52..0000000000 Binary files a/cms/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.eot and /dev/null differ diff --git a/cms/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.svg b/cms/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.svg deleted file mode 100755 index 66a1abd0e8..0000000000 --- a/cms/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cms/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff2 b/cms/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff2 new file mode 100644 index 0000000000..721dbc2c0b Binary files /dev/null and b/cms/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff2 differ diff --git a/cms/static/js/spec/views/pages/course_outline_spec.js b/cms/static/js/spec/views/pages/course_outline_spec.js index 0567baa08c..104eb19980 100644 --- a/cms/static/js/spec/views/pages/course_outline_spec.js +++ b/cms/static/js/spec/views/pages/course_outline_spec.js @@ -1,7 +1,7 @@ -define(["jquery", "sinon", "common/js/spec_helpers/ajax_helpers", "js/views/utils/view_utils", "js/views/pages/course_outline", +define(["jquery", "common/js/spec_helpers/ajax_helpers", "js/views/utils/view_utils", "js/views/pages/course_outline", "js/models/xblock_outline_info", "js/utils/date_utils", "js/spec_helpers/edit_helpers", "common/js/spec_helpers/template_helpers"], - function($, Sinon, AjaxHelpers, ViewUtils, CourseOutlinePage, XBlockOutlineInfo, DateUtils, EditHelpers, TemplateHelpers) { + function($, AjaxHelpers, ViewUtils, CourseOutlinePage, XBlockOutlineInfo, DateUtils, EditHelpers, TemplateHelpers) { describe("CourseOutlinePage", function() { var createCourseOutlinePage, displayNameInput, model, outlinePage, requests, diff --git a/cms/static/sass/assets/_fonts.scss b/cms/static/sass/assets/_fonts.scss index 72cbf75105..65c1c91f3e 100644 --- a/cms/static/sass/assets/_fonts.scss +++ b/cms/static/sass/assets/_fonts.scss @@ -1,13 +1,81 @@ // studio - assets - fonts // ==================== +@font-face { + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-Light-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-Light-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-Light-webfont.ttf') format('truetype'); + font-weight: 300; + font-style: normal; +} -// No subsetting. +@font-face { + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-LightItalic-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-LightItalic-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-LightItalic-webfont.ttf') format('truetype'); + font-weight: 300; + font-style: italic; +} -@include font-face('Open Sans', '../fonts/OpenSans/OpenSans-Light-webfont', 300); -@include font-face('Open Sans', '../fonts/OpenSans/OpenSans-LightItalic-webfont', 300, italic); -@include font-face('Open Sans', '../fonts/OpenSans/OpenSans-Regular-webfont', 400); -@include font-face('Open Sans', '../fonts/OpenSans/OpenSans-Italic-webfont', 400, italic); -@include font-face('Open Sans', '../fonts/OpenSans/OpenSans-Semibold-webfont', 600); -@include font-face('Open Sans', '../fonts/OpenSans/OpenSans-SemiboldItalic-webfont', 600, italic); -@include font-face('Open Sans', '../fonts/OpenSans/OpenSans-Bold-webfont', 700); -@include font-face('Open Sans', '../fonts/OpenSans/OpenSans-BoldItalic-webfont', 700, italic); +@font-face { + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-Regular-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-Regular-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-Regular-webfont.ttf') format('truetype'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-Italic-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-Italic-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-Italic-webfont.ttf') format('truetype'); + font-weight: 400; + font-style: italic; +} + +@font-face { + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-Semibold-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-Semibold-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-Semibold-webfont.ttf') format('truetype'); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.ttf') format('truetype'); + font-weight: 600; + font-style: italic; +} + +@font-face { + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-Bold-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-Bold-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-Bold-webfont.ttf') format('truetype'); + font-weight: 700; + font-style: normal; +} + +@font-face { + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.ttf') format('truetype'); + font-weight: 700; + font-style: italic; +} diff --git a/cms/static/sass/elements/_typography.scss b/cms/static/sass/elements/_typography.scss index cb930f3960..f142e0436e 100644 --- a/cms/static/sass/elements/_typography.scss +++ b/cms/static/sass/elements/_typography.scss @@ -5,7 +5,7 @@ // weights %t-ultrastrong { - font-weight: 800; + font-weight: 700; } %t-strong { font-weight: 600; diff --git a/cms/templates/base.html b/cms/templates/base.html index 948ebf3c58..1e52fb589e 100644 --- a/cms/templates/base.html +++ b/cms/templates/base.html @@ -36,7 +36,7 @@ import json - <%block name="view_notes"> + <%block name="view_notes"> ${_("Skip to main content")} @@ -46,7 +46,7 @@ import json var require = {baseUrl: window.baseUrl}; - + ## js templates + diff --git a/common/djangoapps/student/admin.py b/common/djangoapps/student/admin.py index 4bf11b1215..7f355da572 100644 --- a/common/djangoapps/student/admin.py +++ b/common/djangoapps/student/admin.py @@ -20,7 +20,7 @@ from opaque_keys import InvalidKeyError class CourseAccessRoleForm(forms.ModelForm): """Form for adding new Course Access Roles view the Django Admin Panel.""" - class Meta: + class Meta(object): # pylint: disable=missing-docstring model = CourseAccessRole email = forms.EmailField(required=True) @@ -123,7 +123,7 @@ class CourseAccessRoleAdmin(admin.ModelAdmin): class LinkedInAddToProfileConfigurationAdmin(admin.ModelAdmin): """Admin interface for the LinkedIn Add to Profile configuration. """ - class Meta: + class Meta(object): # pylint: disable=missing-docstring model = LinkedInAddToProfileConfiguration # Exclude deprecated fields diff --git a/common/djangoapps/student/auth.py b/common/djangoapps/student/auth.py index a927bb5097..f2e7b7f914 100644 --- a/common/djangoapps/student/auth.py +++ b/common/djangoapps/student/auth.py @@ -20,7 +20,7 @@ STUDIO_VIEW_CONTENT = 1 # In addition to the above, one is always allowed to "demote" oneself to a lower role within a course, or remove oneself -def has_access(user, role): +def user_has_role(user, role): """ Check whether this user has access to this role (either direct or implied) :param user: @@ -64,14 +64,14 @@ def get_user_permissions(user, course_key, org=None): # global staff, org instructors, and course instructors have all permissions: if GlobalStaff().has_user(user) or OrgInstructorRole(org=org).has_user(user): return all_perms - if course_key and has_access(user, CourseInstructorRole(course_key)): + if course_key and user_has_role(user, CourseInstructorRole(course_key)): return all_perms # Staff have all permissions except EDIT_ROLES: - if OrgStaffRole(org=org).has_user(user) or (course_key and has_access(user, CourseStaffRole(course_key))): + if OrgStaffRole(org=org).has_user(user) or (course_key and user_has_role(user, CourseStaffRole(course_key))): return STUDIO_VIEW_USERS | STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT # Otherwise, for libraries, users can view only: if course_key and isinstance(course_key, LibraryLocator): - if OrgLibraryUserRole(org=org).has_user(user) or has_access(user, LibraryUserRole(course_key)): + if OrgLibraryUserRole(org=org).has_user(user) or user_has_role(user, LibraryUserRole(course_key)): return STUDIO_VIEW_USERS | STUDIO_VIEW_CONTENT return 0 @@ -151,5 +151,5 @@ def _check_caller_authority(caller, role): if isinstance(role, (GlobalStaff, CourseCreatorRole)): raise PermissionDenied elif isinstance(role, CourseRole): # instructors can change the roles w/in their course - if not has_access(caller, CourseInstructorRole(role.course_key)): + if not user_has_role(caller, CourseInstructorRole(role.course_key)): raise PermissionDenied diff --git a/common/djangoapps/student/helpers.py b/common/djangoapps/student/helpers.py index 85c2b6def0..f5ce8a770a 100644 --- a/common/djangoapps/student/helpers.py +++ b/common/djangoapps/student/helpers.py @@ -1,16 +1,12 @@ """Helpers for the student app. """ -import time from datetime import datetime import urllib from pytz import UTC - -from django.utils.http import cookie_date -from django.conf import settings from django.core.urlresolvers import reverse, NoReverseMatch import third_party_auth -from verify_student.models import SoftwareSecurePhotoVerification # pylint: disable=F0401 +from verify_student.models import VerificationDeadline, SoftwareSecurePhotoVerification # pylint: disable=import-error from course_modes.models import CourseMode @@ -23,7 +19,7 @@ VERIFY_STATUS_MISSED_DEADLINE = "verify_missed_deadline" VERIFY_STATUS_NEED_TO_REVERIFY = "verify_need_to_reverify" -def check_verify_status_by_course(user, course_enrollments, all_course_modes): +def check_verify_status_by_course(user, course_enrollments): """ Determine the per-course verification statuses for a given user. @@ -48,8 +44,6 @@ def check_verify_status_by_course(user, course_enrollments, all_course_modes): Arguments: user (User): The currently logged-in user. course_enrollments (list[CourseEnrollment]): The courses the user is enrolled in. - all_course_modes (list): List of all course modes for the student's enrolled courses, - including modes that have expired. Returns: dict: Mapping of course keys verification status dictionaries. @@ -73,24 +67,21 @@ def check_verify_status_by_course(user, course_enrollments, all_course_modes): user, queryset=verifications ) + # Retrieve verification deadlines for the enrolled courses + enrolled_course_keys = [enrollment.course_id for enrollment in course_enrollments] + course_deadlines = VerificationDeadline.deadlines_for_courses(enrolled_course_keys) + recent_verification_datetime = None for enrollment in course_enrollments: - # Get the verified mode (if any) for this course - # We pass in the course modes we have already loaded to avoid - # another database hit, as well as to ensure that expired - # course modes are included in the search. - verified_mode = CourseMode.verified_mode_for_course( - enrollment.course_id, - modes=all_course_modes[enrollment.course_id] - ) + # If the user hasn't enrolled as verified, then the course + # won't display state related to its verification status. + if enrollment.mode in CourseMode.VERIFIED_MODES: - # If no verified mode has ever been offered, or the user hasn't enrolled - # as verified, then the course won't display state related to its - # verification status. - if verified_mode is not None and enrollment.mode in CourseMode.VERIFIED_MODES: - deadline = verified_mode.expiration_datetime + # Retrieve the verification deadline associated with the course. + # This could be None if the course doesn't have a deadline. + deadline = course_deadlines.get(enrollment.course_id) relevant_verification = SoftwareSecurePhotoVerification.verification_for_datetime(deadline, verifications) diff --git a/common/djangoapps/student/migrations/0035_access_roles.py b/common/djangoapps/student/migrations/0035_access_roles.py index a29679bf4c..bf7bec2dc6 100644 --- a/common/djangoapps/student/migrations/0035_access_roles.py +++ b/common/djangoapps/student/migrations/0035_access_roles.py @@ -20,6 +20,11 @@ class Migration(DataMigration): Converts course_creator, instructor_, staff_, and betatestuser_ to new table """ + # Because we instantiate the module store and the modulestore needs this config table to exist. + depends_on = ( + ("xblock_django", "0001_initial"), + ) + GROUP_ENTRY_RE = re.compile(r'(?Pstaff|instructor|beta_testers|course_creator_group)_?(?P.*)') def forwards(self, orm): diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index 23abdd071c..ff9a863c33 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -10,16 +10,19 @@ file and check it in at the same time as your model changes. To do that, 2. ./manage.py lms schemamigration student --auto description_of_your_change 3. Add the migration file created in edx-platform/common/djangoapps/student/migrations/ """ +from collections import defaultdict, OrderedDict from datetime import datetime, timedelta +from functools import total_ordering import hashlib +from importlib import import_module import json import logging from pytz import UTC -import uuid -from collections import defaultdict, OrderedDict -import dogstats_wrapper as dog_stats_api from urllib import urlencode +import uuid +import analytics +from config_models.models import ConfigurationModel from django.utils.translation import ugettext_lazy as _ from django.conf import settings from django.utils import timezone @@ -33,28 +36,21 @@ from django.dispatch import receiver, Signal from django.core.exceptions import ObjectDoesNotExist from django.utils.translation import ugettext_noop from django_countries.fields import CountryField -from config_models.models import ConfigurationModel -from track import contexts +import dogstats_wrapper as dog_stats_api from eventtracking import tracker -from importlib import import_module - -from south.modelsinspector import add_introspection_rules - -from opaque_keys.edx.locations import SlashSeparatedCourseKey - -import lms.lib.comment_client as cc -from util.model_utils import emit_field_changed_events, get_changed_fields_dict -from util.query import use_read_replica_if_available -from xmodule_django.models import CourseKeyField, NoneToEmptyManager -from xmodule.modulestore.exceptions import ItemNotFoundError -from xmodule.modulestore.django import modulestore from opaque_keys.edx.keys import CourseKey -from functools import total_ordering +from opaque_keys.edx.locations import SlashSeparatedCourseKey +from south.modelsinspector import add_introspection_rules +from track import contexts +from xmodule_django.models import CourseKeyField, NoneToEmptyManager from certificates.models import GeneratedCertificate from course_modes.models import CourseMode +import lms.lib.comment_client as cc +from openedx.core.djangoapps.content.course_overviews.models import CourseOverview +from util.model_utils import emit_field_changed_events, get_changed_fields_dict +from util.query import use_read_replica_if_available -import analytics UNENROLL_DONE = Signal(providing_args=["course_enrollment", "skip_refund"]) log = logging.getLogger(__name__) @@ -216,7 +212,7 @@ class UserProfile(models.Model): MITx fall prototype. """ - class Meta: # pylint: disable=missing-docstring + class Meta(object): # pylint: disable=missing-docstring db_table = "auth_userprofile" # CRITICAL TODO/SECURITY @@ -436,7 +432,7 @@ class Registration(models.Model): registration profile is created when the user creates an account, but that account is inactive. Once the user clicks on the activation key, it becomes active. ''' - class Meta: + class Meta(object): # pylint: disable=missing-docstring db_table = "auth_registration" user = models.ForeignKey(User, unique=True) @@ -846,7 +842,7 @@ class CourseEnrollment(models.Model): objects = CourseEnrollmentManager() - class Meta: + class Meta(object): # pylint: disable=missing-docstring unique_together = (('user', 'course_id'),) ordering = ('user', 'course_id') @@ -885,7 +881,7 @@ class CourseEnrollment(models.Model): # save it to the database so that it can have an ID that we can throw # into our CourseEnrollment object. Otherwise, we'll get an # IntegrityError for having a null user_id. - assert(isinstance(course_key, CourseKey)) + assert isinstance(course_key, CourseKey) if user.id is None: user.save() @@ -994,7 +990,7 @@ class CourseEnrollment(models.Model): try: context = contexts.course_context_from_course_id(self.course_id) - assert(isinstance(self.course_id, CourseKey)) + assert isinstance(self.course_id, CourseKey) data = { 'user_id': self.user.id, 'course_id': self.course_id.to_deprecated_string(), @@ -1064,18 +1060,15 @@ class CourseEnrollment(models.Model): """ # All the server-side checks for whether a user is allowed to enroll. try: - course = modulestore().get_course(course_key) - except ItemNotFoundError: - log.warning( - u"User %s failed to enroll in non-existent course %s", - user.username, - course_key.to_deprecated_string(), - ) - raise NonExistentCourseError + course = CourseOverview.get_from_id(course_key) + except CourseOverview.DoesNotExist: + # This is here to preserve legacy behavior which allowed enrollment in courses + # announced before the start of content creation. + if check_access: + log.warning(u"User %s failed to enroll in non-existent course %s", user.username, unicode(course_key)) + raise NonExistentCourseError if check_access: - if course is None: - raise NonExistentCourseError if CourseEnrollment.is_enrollment_closed(user, course): log.warning( u"User %s failed to enroll in course %s because enrollment is closed", @@ -1320,7 +1313,8 @@ class CourseEnrollment(models.Model): @property def course(self): - return modulestore().get_course(self.course_id) + # Deprecated. Please use the `course_overview` property instead. + return self.course_overview @property def course_overview(self): @@ -1334,7 +1328,6 @@ class CourseEnrollment(models.Model): become stale. """ if not self._course_overview: - from openedx.core.djangoapps.content.course_overviews.models import CourseOverview try: self._course_overview = CourseOverview.get_from_id(self.course_id) except (CourseOverview.DoesNotExist, IOError): @@ -1407,7 +1400,7 @@ class CourseEnrollmentAllowed(models.Model): created = models.DateTimeField(auto_now_add=True, null=True, db_index=True) - class Meta: # pylint: disable=missing-docstring + class Meta(object): # pylint: disable=missing-docstring unique_together = (('email', 'course_id'),) def __unicode__(self): @@ -1444,7 +1437,7 @@ class CourseAccessRole(models.Model): course_id = CourseKeyField(max_length=255, db_index=True, blank=True) role = models.CharField(max_length=64, db_index=True) - class Meta: # pylint: disable=missing-docstring + class Meta(object): # pylint: disable=missing-docstring unique_together = ('user', 'org', 'course_id', 'role') @property @@ -1835,7 +1828,7 @@ class LanguageProficiency(models.Model): /edx-platform/openedx/core/djangoapps/user_api/accounts/views.py or its associated api method (update_account_settings) so that the events are emitted. """ - class Meta: + class Meta(object): # pylint: disable=missing-docstring unique_together = (('code', 'user_profile'),) user_profile = models.ForeignKey(UserProfile, db_index=True, related_name='language_proficiencies') diff --git a/common/djangoapps/student/roles.py b/common/djangoapps/student/roles.py index b2127bee41..8172fea0a5 100644 --- a/common/djangoapps/student/roles.py +++ b/common/djangoapps/student/roles.py @@ -99,7 +99,7 @@ class GlobalStaff(AccessRole): def add_users(self, *users): for user in users: - if (user.is_authenticated() and user.is_active): + if user.is_authenticated() and user.is_active: user.is_staff = True user.save() diff --git a/common/djangoapps/student/tests/test_authz.py b/common/djangoapps/student/tests/test_authz.py index 655e240aab..e66da9622b 100644 --- a/common/djangoapps/student/tests/test_authz.py +++ b/common/djangoapps/student/tests/test_authz.py @@ -9,7 +9,7 @@ from django.core.exceptions import PermissionDenied from student.roles import CourseInstructorRole, CourseStaffRole, CourseCreatorRole from student.tests.factories import AdminFactory -from student.auth import has_access, add_users, remove_users +from student.auth import user_has_role, add_users, remove_users from opaque_keys.edx.locations import SlashSeparatedCourseKey @@ -30,30 +30,30 @@ class CreatorGroupTest(TestCase): Tests that CourseCreatorRole().has_user always returns True if ENABLE_CREATOR_GROUP and DISABLE_COURSE_CREATION are both not turned on. """ - self.assertTrue(has_access(self.user, CourseCreatorRole())) + self.assertTrue(user_has_role(self.user, CourseCreatorRole())) def test_creator_group_enabled_but_empty(self): """ Tests creator group feature on, but group empty. """ with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): - self.assertFalse(has_access(self.user, CourseCreatorRole())) + self.assertFalse(user_has_role(self.user, CourseCreatorRole())) # Make user staff. This will cause CourseCreatorRole().has_user to return True. self.user.is_staff = True - self.assertTrue(has_access(self.user, CourseCreatorRole())) + self.assertTrue(user_has_role(self.user, CourseCreatorRole())) def test_creator_group_enabled_nonempty(self): """ Tests creator group feature on, user added. """ with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): add_users(self.admin, CourseCreatorRole(), self.user) - self.assertTrue(has_access(self.user, CourseCreatorRole())) + self.assertTrue(user_has_role(self.user, CourseCreatorRole())) # check that a user who has not been added to the group still returns false user_not_added = User.objects.create_user('testuser2', 'test+courses2@edx.org', 'foo2') - self.assertFalse(has_access(user_not_added, CourseCreatorRole())) + self.assertFalse(user_has_role(user_not_added, CourseCreatorRole())) # remove first user from the group and verify that CourseCreatorRole().has_user now returns false remove_users(self.admin, CourseCreatorRole(), self.user) - self.assertFalse(has_access(self.user, CourseCreatorRole())) + self.assertFalse(user_has_role(self.user, CourseCreatorRole())) def test_course_creation_disabled(self): """ Tests that the COURSE_CREATION_DISABLED flag overrides course creator group settings. """ @@ -63,15 +63,15 @@ class CreatorGroupTest(TestCase): add_users(self.admin, CourseCreatorRole(), self.user) # DISABLE_COURSE_CREATION overrides (user is not marked as staff). - self.assertFalse(has_access(self.user, CourseCreatorRole())) + self.assertFalse(user_has_role(self.user, CourseCreatorRole())) # Mark as staff. Now CourseCreatorRole().has_user returns true. self.user.is_staff = True - self.assertTrue(has_access(self.user, CourseCreatorRole())) + self.assertTrue(user_has_role(self.user, CourseCreatorRole())) # Remove user from creator group. CourseCreatorRole().has_user still returns true because is_staff=True remove_users(self.admin, CourseCreatorRole(), self.user) - self.assertTrue(has_access(self.user, CourseCreatorRole())) + self.assertTrue(user_has_role(self.user, CourseCreatorRole())) def test_add_user_not_authenticated(self): """ @@ -84,7 +84,7 @@ class CreatorGroupTest(TestCase): anonymous_user = AnonymousUser() role = CourseCreatorRole() add_users(self.admin, role, anonymous_user) - self.assertFalse(has_access(anonymous_user, role)) + self.assertFalse(user_has_role(anonymous_user, role)) def test_add_user_not_active(self): """ @@ -96,7 +96,7 @@ class CreatorGroupTest(TestCase): ): self.user.is_active = False add_users(self.admin, CourseCreatorRole(), self.user) - self.assertFalse(has_access(self.user, CourseCreatorRole())) + self.assertFalse(user_has_role(self.user, CourseCreatorRole())) def test_add_user_to_group_requires_staff_access(self): with self.assertRaises(PermissionDenied): @@ -150,15 +150,15 @@ class CourseGroupTest(TestCase): Tests adding user to course group (happy path). """ # Create groups for a new course (and assign instructor role to the creator). - self.assertFalse(has_access(self.creator, CourseInstructorRole(self.course_key))) + self.assertFalse(user_has_role(self.creator, CourseInstructorRole(self.course_key))) add_users(self.global_admin, CourseInstructorRole(self.course_key), self.creator) add_users(self.global_admin, CourseStaffRole(self.course_key), self.creator) - self.assertTrue(has_access(self.creator, CourseInstructorRole(self.course_key))) + self.assertTrue(user_has_role(self.creator, CourseInstructorRole(self.course_key))) # Add another user to the staff role. - self.assertFalse(has_access(self.staff, CourseStaffRole(self.course_key))) + self.assertFalse(user_has_role(self.staff, CourseStaffRole(self.course_key))) add_users(self.creator, CourseStaffRole(self.course_key), self.staff) - self.assertTrue(has_access(self.staff, CourseStaffRole(self.course_key))) + self.assertTrue(user_has_role(self.staff, CourseStaffRole(self.course_key))) def test_add_user_to_course_group_permission_denied(self): """ @@ -177,13 +177,13 @@ class CourseGroupTest(TestCase): add_users(self.global_admin, CourseStaffRole(self.course_key), self.creator) add_users(self.creator, CourseStaffRole(self.course_key), self.staff) - self.assertTrue(has_access(self.staff, CourseStaffRole(self.course_key))) + self.assertTrue(user_has_role(self.staff, CourseStaffRole(self.course_key))) remove_users(self.creator, CourseStaffRole(self.course_key), self.staff) - self.assertFalse(has_access(self.staff, CourseStaffRole(self.course_key))) + self.assertFalse(user_has_role(self.staff, CourseStaffRole(self.course_key))) remove_users(self.creator, CourseInstructorRole(self.course_key), self.creator) - self.assertFalse(has_access(self.creator, CourseInstructorRole(self.course_key))) + self.assertFalse(user_has_role(self.creator, CourseInstructorRole(self.course_key))) def test_remove_user_from_course_group_permission_denied(self): """ diff --git a/common/djangoapps/student/tests/test_course_listing.py b/common/djangoapps/student/tests/test_course_listing.py index cdf75a342b..362d85b95e 100644 --- a/common/djangoapps/student/tests/test_course_listing.py +++ b/common/djangoapps/student/tests/test_course_listing.py @@ -2,26 +2,27 @@ Unit tests for getting the list of courses for a user through iterating all courses and by reversing group name formats. """ -import mock -from mock import patch, Mock +import unittest -from student.tests.factories import UserFactory +from django.conf import settings +from django.test.client import Client +import mock + +from openedx.core.djangoapps.content.course_overviews.models import CourseOverview +from student.models import CourseEnrollment from student.roles import GlobalStaff +from student.tests.factories import UserFactory +from student.views import get_course_enrollments +from xmodule.error_module import ErrorDescriptor from xmodule.modulestore import ModuleStoreEnum +from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory -from xmodule.modulestore.django import modulestore -from xmodule.error_module import ErrorDescriptor -from django.test.client import Client -from student.models import CourseEnrollment -from student.views import get_course_enrollments from util.milestones_helpers import ( get_pre_requisite_courses_not_completed, set_prerequisite_courses, seed_milestone_relationship_types ) -import unittest -from django.conf import settings class TestCourseListing(ModuleStoreTestCase): @@ -91,10 +92,12 @@ class TestCourseListing(ModuleStoreTestCase): course_key = mongo_store.make_course_key('Org1', 'Course1', 'Run1') self._create_course_with_access_groups(course_key, default_store=ModuleStoreEnum.Type.mongo) - with patch('xmodule.modulestore.mongo.base.MongoKeyValueStore', Mock(side_effect=Exception)): + with mock.patch('xmodule.modulestore.mongo.base.MongoKeyValueStore', mock.Mock(side_effect=Exception)): self.assertIsInstance(modulestore().get_course(course_key), ErrorDescriptor) - # get courses through iterating all courses + # Invalidate (e.g., delete) the corresponding CourseOverview, forcing get_course to be called. + CourseOverview.objects.filter(id=course_key).delete() + courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(courses_list, []) diff --git a/common/djangoapps/student/tests/test_credit.py b/common/djangoapps/student/tests/test_credit.py index 3167069ccb..b85d711e2d 100644 --- a/common/djangoapps/student/tests/test_credit.py +++ b/common/djangoapps/student/tests/test_credit.py @@ -6,7 +6,6 @@ import datetime from mock import patch import pytz -from mock import patch from django.conf import settings from django.core.urlresolvers import reverse diff --git a/common/djangoapps/student/tests/test_email.py b/common/djangoapps/student/tests/test_email.py index f04fd5b51e..d7aaf01180 100644 --- a/common/djangoapps/student/tests/test_email.py +++ b/common/djangoapps/student/tests/test_email.py @@ -11,11 +11,11 @@ from student.views import ( from student.models import UserProfile, PendingEmailChange from django.core.urlresolvers import reverse from django.core import mail -from django.contrib.auth.models import User, AnonymousUser +from django.contrib.auth.models import User from django.test import TestCase, TransactionTestCase from django.test.client import RequestFactory from mock import Mock, patch -from django.http import Http404, HttpResponse +from django.http import HttpResponse from django.conf import settings from edxmako.shortcuts import render_to_string from edxmako.tests import mako_middleware_process_request diff --git a/common/djangoapps/student/tests/test_login_registration_forms.py b/common/djangoapps/student/tests/test_login_registration_forms.py index 3b0606d8b9..a17161ed0a 100644 --- a/common/djangoapps/student/tests/test_login_registration_forms.py +++ b/common/djangoapps/student/tests/test_login_registration_forms.py @@ -1,7 +1,6 @@ """Tests for the login and registration form rendering. """ import urllib import unittest -from collections import OrderedDict import ddt from mock import patch @@ -10,7 +9,6 @@ from django.core.urlresolvers import reverse from util.testing import UrlResetMixin from xmodule.modulestore.tests.factories import CourseFactory -from student.tests.factories import CourseModeFactory from third_party_auth.tests.testutil import ThirdPartyAuthTestMixin from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase diff --git a/common/djangoapps/student/tests/test_recent_enrollments.py b/common/djangoapps/student/tests/test_recent_enrollments.py index 07516af01a..2fd54d87bf 100644 --- a/common/djangoapps/student/tests/test_recent_enrollments.py +++ b/common/djangoapps/student/tests/test_recent_enrollments.py @@ -112,10 +112,10 @@ class TestRecentEnrollments(ModuleStoreTestCase): recent_course_list = _get_recently_enrolled_courses(courses_list) self.assertEqual(len(recent_course_list), 5) - self.assertEqual(recent_course_list[1].course, courses[0]) - self.assertEqual(recent_course_list[2].course, courses[1]) - self.assertEqual(recent_course_list[3].course, courses[2]) - self.assertEqual(recent_course_list[4].course, courses[3]) + self.assertEqual(recent_course_list[1].course.id, courses[0].id) + self.assertEqual(recent_course_list[2].course.id, courses[1].id) + self.assertEqual(recent_course_list[3].course.id, courses[2].id) + self.assertEqual(recent_course_list[4].course.id, courses[3].id) def test_dashboard_rendering(self): """ diff --git a/common/djangoapps/student/tests/test_verification_status.py b/common/djangoapps/student/tests/test_verification_status.py index d738f0a55e..140b2f71d4 100644 --- a/common/djangoapps/student/tests/test_verification_status.py +++ b/common/djangoapps/student/tests/test_verification_status.py @@ -20,7 +20,7 @@ from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from student.tests.factories import UserFactory, CourseEnrollmentFactory from course_modes.tests.factories import CourseModeFactory -from verify_student.models import SoftwareSecurePhotoVerification # pylint: disable=F0401 +from verify_student.models import VerificationDeadline, SoftwareSecurePhotoVerification # pylint: disable=import-error from util.testing import UrlResetMixin @@ -61,9 +61,11 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase): mode="verified" ) - # The default course has no verified mode, - # so no verification status should be displayed - self._assert_course_verification_status(None) + # Continue to show the student as needing to verify. + # The student is enrolled as verified, so we might as well let them + # complete verification. We'd need to change their enrollment mode + # anyway to ensure that the student is issued the correct kind of certificate. + self._assert_course_verification_status(VERIFY_STATUS_NEED_TO_VERIFY) def test_need_to_verify_no_expiration(self): self._setup_mode_and_enrollment(None, "verified") @@ -285,6 +287,7 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase): user=self.user, mode=enrollment_mode ) + VerificationDeadline.set_deadline(self.course.id, deadline) BANNER_ALT_MESSAGES = { None: "Honor", diff --git a/common/djangoapps/student/tests/tests.py b/common/djangoapps/student/tests/tests.py index e2e66fb0c9..42842cab37 100644 --- a/common/djangoapps/student/tests/tests.py +++ b/common/djangoapps/student/tests/tests.py @@ -10,18 +10,20 @@ import ddt from django.conf import settings from django.contrib.auth.models import User, AnonymousUser -from django.contrib.sessions.middleware import SessionMiddleware from django.core.urlresolvers import reverse from django.test import TestCase -from django.test.client import RequestFactory, Client +from django.test.client import Client from mock import Mock, patch from opaque_keys.edx.locations import SlashSeparatedCourseKey from student.models import ( anonymous_id_for_user, user_by_anonymous_id, CourseEnrollment, unique_id_for_user, LinkedInAddToProfileConfiguration ) -from student.views import (process_survey_link, _cert_info, - change_enrollment, complete_course_mode_info) +from student.views import ( + process_survey_link, + _cert_info, + complete_course_mode_info, +) from student.tests.factories import UserFactory, CourseModeFactory from util.testing import EventTestMixin from util.model_utils import USER_SETTINGS_CHANGED_EVENT_NAME @@ -492,9 +494,9 @@ class DashboardTest(ModuleStoreTestCase): """ Check that the student dashboard makes use of course metadata caching. - The first time the student dashboard displays a specific course, it will - make a call to the module store. After that first request, though, the - course's metadata should be cached as a CourseOverview. + After enrolling a student in a course, that course's metadata should be + cached as a CourseOverview. The student dashboard should never have to make + calls to the modulestore. Arguments: modulestore_type (ModuleStoreEnum.Type): Type of modulestore to create @@ -509,23 +511,21 @@ class DashboardTest(ModuleStoreTestCase): involve adding fields to CourseOverview so that loading a full CourseDescriptor isn't necessary. """ - # Create a course, log in the user, and enroll them in the course. + # Create a course and log in the user. test_course = CourseFactory.create(default_store=modulestore_type) self.client.login(username="jack", password="test") - CourseEnrollment.enroll(self.user, test_course.id) - # The first request will result in a modulestore query. + # Enrolling the user in the course will result in a modulestore query. with check_mongo_calls(expected_mongo_calls): - response_1 = self.client.get(reverse('dashboard')) - self.assertEquals(response_1.status_code, 200) + CourseEnrollment.enroll(self.user, test_course.id) # Subsequent requests will only result in SQL queries to load the # CourseOverview object that has been created. with check_mongo_calls(0): + response_1 = self.client.get(reverse('dashboard')) + self.assertEquals(response_1.status_code, 200) response_2 = self.client.get(reverse('dashboard')) self.assertEquals(response_2.status_code, 200) - response_3 = self.client.get(reverse('dashboard')) - self.assertEquals(response_3.status_code, 200) @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @patch.dict(settings.FEATURES, {"IS_EDX_DOMAIN": True}) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 53551510fa..1dc601ad20 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -6,7 +6,6 @@ import logging import uuid import json import warnings -from datetime import timedelta from collections import defaultdict from pytz import UTC from requests import HTTPError @@ -26,9 +25,8 @@ from django.db import IntegrityError, transaction from django.http import (HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseServerError, Http404) from django.shortcuts import redirect -from django.utils import timezone from django.utils.translation import ungettext -from django.utils.http import cookie_date, base36_to_int +from django.utils.http import base36_to_int from django.utils.translation import ugettext as _, get_language from django.views.decorators.cache import never_cache from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie @@ -49,7 +47,7 @@ from edxmako.shortcuts import render_to_response, render_to_string from course_modes.models import CourseMode from shoppingcart.api import order_history from student.models import ( - Registration, UserProfile, PendingNameChange, + Registration, UserProfile, PendingEmailChange, CourseEnrollment, CourseEnrollmentAttribute, unique_id_for_user, CourseEnrollmentAllowed, UserStanding, LoginFailures, create_comments_service_user, PasswordHistory, UserSignupSource, @@ -60,13 +58,12 @@ from verify_student.models import SoftwareSecurePhotoVerification # pylint: dis from certificates.models import CertificateStatuses, certificate_status_for_student from certificates.api import ( # pylint: disable=import-error get_certificate_url, - get_active_web_certificate, has_html_certificates_enabled, ) -from dark_lang.models import DarkLangConfig from xmodule.modulestore.django import modulestore from opaque_keys import InvalidKeyError +from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locator import CourseLocator from xmodule.modulestore import ModuleStoreEnum @@ -86,7 +83,6 @@ from external_auth.login_and_register import ( ) from bulk_email.models import Optout, CourseAuthorization -import shoppingcart from lang_pref import LANGUAGE_KEY import track.views @@ -537,7 +533,7 @@ def dashboard(request): # Retrieve the course modes for each course enrolled_course_ids = [enrollment.course_id for enrollment in course_enrollments] - all_course_modes, unexpired_course_modes = CourseMode.all_and_unexpired_modes_for_courses(enrolled_course_ids) + __, unexpired_course_modes = CourseMode.all_and_unexpired_modes_for_courses(enrolled_course_ids) course_modes_by_course = { course_id: { mode.slug: mode @@ -600,11 +596,7 @@ def dashboard(request): # # If a course is not included in this dictionary, # there is no verification messaging to display. - verify_status_by_course = check_verify_status_by_course( - user, - course_enrollments, - all_course_modes - ) + verify_status_by_course = check_verify_status_by_course(user, course_enrollments) cert_statuses = { enrollment.course_id: cert_info(request.user, enrollment.course_overview, enrollment.mode) for enrollment in course_enrollments @@ -873,7 +865,7 @@ def _credit_statuses(user, course_enrollments): statuses = {} for eligibility in credit_api.get_eligibilities_for_user(user.username): - course_key = eligibility["course_key"] + course_key = CourseKey.from_string(unicode(eligibility["course_key"])) status = { "course_key": unicode(course_key), "eligible": True, @@ -1049,7 +1041,7 @@ def accounts_login(request): # Need different levels of logging @ensure_csrf_cookie -def login_user(request, error=""): # pylint: disable-msg=too-many-statements,unused-argument +def login_user(request, error=""): # pylint: disable=too-many-statements,unused-argument """AJAX request to log in the user.""" backend_name = None @@ -1091,9 +1083,9 @@ def login_user(request, error=""): # pylint: disable-msg=too-many-statements,un platform_name=settings.PLATFORM_NAME, provider_name=requested_provider.name ) + "

" + - _("If you don't have an {platform_name} account yet, click Register Now at the top of the page.").format( - platform_name=settings.PLATFORM_NAME - ), + _("If you don't have an {platform_name} account yet, " + "click Register at the top of the page.").format( + platform_name=settings.PLATFORM_NAME), content_type="text/plain", status=403 ) diff --git a/common/djangoapps/terrain/setup_prereqs.py b/common/djangoapps/terrain/setup_prereqs.py index 98f5c67983..90337c3867 100644 --- a/common/djangoapps/terrain/setup_prereqs.py +++ b/common/djangoapps/terrain/setup_prereqs.py @@ -28,8 +28,7 @@ SERVICES = { YOUTUBE_API_URLS = { 'main': 'https://www.youtube.com/', - 'player': 'http://www.youtube.com/iframe_api', - 'metadata': 'http://gdata.youtube.com/feeds/api/videos/', + 'player': 'https://www.youtube.com/iframe_api', # For transcripts, you need to check an actual video, so we will # just specify our default video and see if that one is available. 'transcript': 'http://video.google.com/timedtext?lang=en&v=OEoXaMPEzfM', diff --git a/common/djangoapps/terrain/steps.py b/common/djangoapps/terrain/steps.py index 616991c58d..7006c42389 100644 --- a/common/djangoapps/terrain/steps.py +++ b/common/djangoapps/terrain/steps.py @@ -65,7 +65,7 @@ def i_should_be_on_the_dashboard(step): @step(u'I (?:visit|access|open) the courses page$') def i_am_on_the_courses_page(step): world.visit('/courses') - assert world.is_css_present('section.courses') + assert world.is_css_present('div.courses') @step(u'I press the "([^"]*)" button$') @@ -95,7 +95,7 @@ def the_page_title_should_be(step, title): @step(u'the page title should contain "([^"]*)"$') def the_page_title_should_contain(step, title): - assert(title in world.browser.title) + assert title in world.browser.title @step('I log in$') diff --git a/common/djangoapps/terrain/stubs/youtube.py b/common/djangoapps/terrain/stubs/youtube.py index af3a87f5ec..27f9d5ef2e 100644 --- a/common/djangoapps/terrain/stubs/youtube.py +++ b/common/djangoapps/terrain/stubs/youtube.py @@ -95,6 +95,9 @@ class StubYouTubeHandler(StubHttpRequestHandler): if self.server.config.get('youtube_api_blocked'): self.send_response(404, content='', headers={'Content-type': 'text/plain'}) else: + # Delay the response to simulate network latency + time.sleep(self.server.config.get('time_to_response', self.DEFAULT_DELAY_SEC)) + # Get the response to send from YouTube. # We need to do this every time because Google sometimes sends different responses # as part of their own experiments, which has caused our tests to become "flaky" @@ -117,17 +120,16 @@ class StubYouTubeHandler(StubHttpRequestHandler): # Construct the response content callback = self.get_params['callback'] - youtube_metadata = json.loads( - requests.get( - "http://gdata.youtube.com/feeds/api/videos/{id}?v=2&alt=jsonc".format(id=youtube_id) - ).text - ) + data = OrderedDict({ - 'data': OrderedDict({ - 'id': youtube_id, - 'message': message, - 'duration': youtube_metadata['data']['duration'], - }) + 'items': list( + OrderedDict({ + 'contentDetails': OrderedDict({ + 'id': youtube_id, + 'duration': 'PT2M20S', + }) + }) + ) }) response = "{cb}({data})".format(cb=callback, data=json.dumps(data)) diff --git a/common/djangoapps/third_party_auth/pipeline.py b/common/djangoapps/third_party_auth/pipeline.py index 5bc4f069dd..866f66e4f3 100644 --- a/common/djangoapps/third_party_auth/pipeline.py +++ b/common/djangoapps/third_party_auth/pipeline.py @@ -58,7 +58,7 @@ See http://psa.matiasaguirre.net/docs/pipeline.html for more docs. """ import random -import string # pylint: disable-msg=deprecated-module +import string # pylint: disable=deprecated-module from collections import OrderedDict import urllib import analytics @@ -80,9 +80,6 @@ from logging import getLogger from . import provider -# Note that this lives in openedx, so this dependency should be refactored. -from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in - # These are the query string params you can pass # to the URL that starts the authentication process. @@ -434,7 +431,7 @@ def running(request): # Pipeline functions. # Signatures are set by python-social-auth; prepending 'unused_' causes # TypeError on dispatch to the auth backend's authenticate(). -# pylint: disable-msg=unused-argument +# pylint: disable=unused-argument def parse_query_params(strategy, response, *args, **kwargs): diff --git a/common/djangoapps/third_party_auth/tests/specs/base.py b/common/djangoapps/third_party_auth/tests/specs/base.py index 4b431069fd..f1bed2ef5a 100644 --- a/common/djangoapps/third_party_auth/tests/specs/base.py +++ b/common/djangoapps/third_party_auth/tests/specs/base.py @@ -1,6 +1,5 @@ """Base integration test for provider implementations.""" -import re import unittest import json diff --git a/common/djangoapps/third_party_auth/tests/specs/test_google.py b/common/djangoapps/third_party_auth/tests/specs/test_google.py index d591c1e594..4a83bb7e74 100644 --- a/common/djangoapps/third_party_auth/tests/specs/test_google.py +++ b/common/djangoapps/third_party_auth/tests/specs/test_google.py @@ -1,6 +1,5 @@ """Integration tests for Google providers.""" -from third_party_auth import provider from third_party_auth.tests.specs import base diff --git a/common/djangoapps/third_party_auth/tests/specs/test_linkedin.py b/common/djangoapps/third_party_auth/tests/specs/test_linkedin.py index c149065115..a5f0e61cc7 100644 --- a/common/djangoapps/third_party_auth/tests/specs/test_linkedin.py +++ b/common/djangoapps/third_party_auth/tests/specs/test_linkedin.py @@ -1,6 +1,5 @@ """Integration tests for LinkedIn providers.""" -from third_party_auth import provider from third_party_auth.tests.specs import base diff --git a/common/djangoapps/third_party_auth/tests/test_pipeline.py b/common/djangoapps/third_party_auth/tests/test_pipeline.py index c4387626ea..18c4458545 100644 --- a/common/djangoapps/third_party_auth/tests/test_pipeline.py +++ b/common/djangoapps/third_party_auth/tests/test_pipeline.py @@ -2,13 +2,13 @@ import random -from third_party_auth import pipeline, provider +from third_party_auth import pipeline from third_party_auth.tests import testutil import unittest -# Allow tests access to protected methods (or module-protected methods) under -# test. pylint: disable-msg=protected-access +# Allow tests access to protected methods (or module-protected methods) under test. +# pylint: disable=protected-access class MakeRandomPasswordTest(testutil.TestCase): diff --git a/common/djangoapps/third_party_auth/tests/test_pipeline_integration.py b/common/djangoapps/third_party_auth/tests/test_pipeline_integration.py index d21d834c93..66294a5cae 100644 --- a/common/djangoapps/third_party_auth/tests/test_pipeline_integration.py +++ b/common/djangoapps/third_party_auth/tests/test_pipeline_integration.py @@ -13,7 +13,7 @@ from social.apps.django_app.default import models as social_models # Get Django User model by reference from python-social-auth. Not a type # constant, pylint. -User = social_models.DjangoStorage.user.user_model() # pylint: disable-msg=invalid-name +User = social_models.DjangoStorage.user.user_model() # pylint: disable=invalid-name class TestCase(testutil.TestCase, test.TestCase): diff --git a/common/djangoapps/third_party_auth/tests/test_settings.py b/common/djangoapps/third_party_auth/tests/test_settings.py index 1c1229190e..9108ce9c66 100644 --- a/common/djangoapps/third_party_auth/tests/test_settings.py +++ b/common/djangoapps/third_party_auth/tests/test_settings.py @@ -21,10 +21,10 @@ _SETTINGS_MAP = { class SettingsUnitTest(testutil.TestCase): """Unit tests for settings management code.""" - # Allow access to protected methods (or module-protected methods) under - # test. pylint: disable-msg=protected-access + # Allow access to protected methods (or module-protected methods) under test. + # pylint: disable=protected-access # Suppress sprurious no-member warning on fakes. - # pylint: disable-msg=no-member + # pylint: disable=no-member def setUp(self): super(SettingsUnitTest, self).setUp() diff --git a/common/djangoapps/track/backends/django.py b/common/djangoapps/track/backends/django.py index fe60cc4478..4fffc86d25 100644 --- a/common/djangoapps/track/backends/django.py +++ b/common/djangoapps/track/backends/django.py @@ -46,7 +46,7 @@ class TrackingLog(models.Model): time = models.DateTimeField('event time') host = models.CharField(max_length=64, blank=True) - class Meta: + class Meta(object): # pylint: disable=missing-docstring app_label = 'track' db_table = 'track_trackinglog' diff --git a/common/djangoapps/track/contexts.py b/common/djangoapps/track/contexts.py index ee15a06d67..1f7c94c26e 100644 --- a/common/djangoapps/track/contexts.py +++ b/common/djangoapps/track/contexts.py @@ -49,7 +49,7 @@ def course_context_from_course_id(course_id): return {'course_id': '', 'org_id': ''} # TODO: Make this accept any CourseKey, and serialize it using .to_string - assert(isinstance(course_id, CourseKey)) + assert isinstance(course_id, CourseKey) return { 'course_id': course_id.to_deprecated_string(), 'org_id': course_id.org, diff --git a/common/djangoapps/track/models.py b/common/djangoapps/track/models.py index 228819b059..c59cf6502a 100644 --- a/common/djangoapps/track/models.py +++ b/common/djangoapps/track/models.py @@ -1 +1,2 @@ +# pylint: disable=unused-import, missing-docstring from track.backends.django import TrackingLog diff --git a/common/djangoapps/track/views/tests/test_views.py b/common/djangoapps/track/views/tests/test_views.py index 18c684fda5..7e23136b3b 100644 --- a/common/djangoapps/track/views/tests/test_views.py +++ b/common/djangoapps/track/views/tests/test_views.py @@ -3,18 +3,14 @@ from mock import patch, sentinel from django.contrib.auth.models import User -from django.test import TestCase from django.test.client import RequestFactory from django.test.utils import override_settings -from eventtracking import tracker from track import views from track.middleware import TrackMiddleware from track.tests import EventTrackingTestCase, FROZEN_TIME from openedx.core.lib.tests.assertions.events import assert_event_matches -from datetime import datetime - class TestTrackViews(EventTrackingTestCase): diff --git a/common/lib/capa/capa/capa_problem.py b/common/lib/capa/capa/capa_problem.py index 42569d383e..f8781b841c 100644 --- a/common/lib/capa/capa/capa_problem.py +++ b/common/lib/capa/capa/capa_problem.py @@ -631,7 +631,7 @@ class LoncapaProblem(object): parent = inc.getparent() parent.insert(parent.index(inc), incxml) parent.remove(inc) - log.debug('Included %s into %s' % (filename, self.problem_id)) + log.debug('Included %s into %s', filename, self.problem_id) def _extract_system_path(self, script): """ @@ -853,7 +853,7 @@ class LoncapaProblem(object): answer_id = 1 input_tags = inputtypes.registry.registered_tags() inputfields = tree.xpath( - "|".join(['//' + response.tag + '[@id=$id]//' + x for x in (input_tags + solution_tags)]), + "|".join(['//' + response.tag + '[@id=$id]//' + x for x in input_tags + solution_tags]), id=response_id_str ) diff --git a/common/lib/capa/capa/checker.py b/common/lib/capa/capa/checker.py index 91e904fe41..381feac333 100755 --- a/common/lib/capa/capa/checker.py +++ b/common/lib/capa/capa/checker.py @@ -99,7 +99,7 @@ def check_that_blanks_fail(problem): for answer_id in problem.get_question_answers()) grading_results = problem.grade_answers(blank_answers) try: - assert(all(result == 'incorrect' for result in grading_results.values())) + assert all(result == 'incorrect' for result in grading_results.values()) except AssertionError: log.error("Blank accepted as correct answer in {0} for {1}" .format(problem, diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py index 62a060c046..cac18d88cd 100644 --- a/common/lib/capa/capa/responsetypes.py +++ b/common/lib/capa/capa/responsetypes.py @@ -2719,7 +2719,7 @@ class ExternalResponse(LoncapaResponse): exans = [''] * len(self.answer_ids) exans[0] = msg - if not (len(exans) == len(self.answer_ids)): + if not len(exans) == len(self.answer_ids): log.error('Expected %s answers from external server, only got %s!', len(self.answer_ids), len(exans)) raise Exception('Short response from external server') diff --git a/common/lib/capa/capa/tests/response_xml_factory.py b/common/lib/capa/capa/tests/response_xml_factory.py index 922a96189c..a1b8f53554 100644 --- a/common/lib/capa/capa/tests/response_xml_factory.py +++ b/common/lib/capa/capa/tests/response_xml_factory.py @@ -80,7 +80,7 @@ class ResponseXMLFactory(object): # Add input elements for __ in range(int(num_inputs)): input_element = self.create_input_element(**kwargs) - if not (None == input_element): + if not None == input_element: response_element.append(input_element) # The problem has an explanation of the solution @@ -146,7 +146,7 @@ class ResponseXMLFactory(object): choice_names = kwargs.get('choice_names', [None] * len(choices)) # Create the , , or element - assert(choice_type in group_element_names) + assert choice_type in group_element_names group_element = etree.Element(group_element_names[choice_type]) # Create the elements @@ -412,8 +412,8 @@ class FormulaResponseXMLFactory(ResponseXMLFactory): answer = kwargs.get("answer", None) hint_list = kwargs.get("hints", None) - assert(answer) - assert(sample_dict and num_samples) + assert answer + assert sample_dict and num_samples # Create the element response_element = etree.Element("formularesponse") @@ -518,7 +518,7 @@ class ImageResponseXMLFactory(ResponseXMLFactory): rectangle = kwargs.get('rectangle', None) regions = kwargs.get('regions', None) - assert(rectangle or regions) + assert rectangle or regions # Create the element input_element = etree.Element("imageinput") @@ -635,9 +635,9 @@ class OptionResponseXMLFactory(ResponseXMLFactory): options_list = kwargs.get('options', None) correct_option = kwargs.get('correct_option', None) - assert(options_list and correct_option) - assert(len(options_list) > 1) - assert(correct_option in options_list) + assert options_list and correct_option + assert len(options_list) > 1 + assert correct_option in options_list # Create the element optioninput_element = etree.Element("optioninput") diff --git a/common/lib/safe_lxml/safe_lxml/etree.py b/common/lib/safe_lxml/safe_lxml/etree.py index 97bc0b7547..c087e99052 100644 --- a/common/lib/safe_lxml/safe_lxml/etree.py +++ b/common/lib/safe_lxml/safe_lxml/etree.py @@ -12,7 +12,7 @@ from lxml.etree import XMLParser as _XMLParser from lxml.etree import _Element, _ElementTree # pylint: disable=unused-import, no-name-in-module # This should be imported after lxml.etree so that it overrides the following attributes. -from defusedxml.lxml import parse, fromstring, XML +from defusedxml.lxml import parse, fromstring, XML # pylint: disable=unused-import class XMLParser(_XMLParser): # pylint: disable=function-redefined diff --git a/common/lib/symmath/symmath/formula.py b/common/lib/symmath/symmath/formula.py index c9166233a1..d5f3e038eb 100644 --- a/common/lib/symmath/symmath/formula.py +++ b/common/lib/symmath/symmath/formula.py @@ -309,7 +309,7 @@ class formula(object): with 'scriptN'. There have been problems using script_N or script(N) """ for child in parent: - if (gettag(child) == 'mstyle' and child.get('mathvariant') == 'script'): + if gettag(child) == 'mstyle' and child.get('mathvariant') == 'script': newchild = etree.Element('mi') newchild.text = 'script%s' % flatten_pmathml(child[0]) parent.replace(child, newchild) @@ -397,7 +397,7 @@ class formula(object): """ for child in parent: # fix msubsup - if (gettag(child) == 'msubsup' and len(child) == 3): + if gettag(child) == 'msubsup' and len(child) == 3: newchild = etree.Element('msup') newbase = etree.Element('mi') newbase.text = '%s_%s' % (flatten_pmathml(child[0]), flatten_pmathml(child[1])) diff --git a/common/lib/symmath/symmath/symmath_check.py b/common/lib/symmath/symmath/symmath_check.py index d39afb35fb..6e5f05212c 100644 --- a/common/lib/symmath/symmath/symmath_check.py +++ b/common/lib/symmath/symmath/symmath_check.py @@ -86,7 +86,7 @@ def check(expect, given, numerical=False, matrix=False, normphase=False, abcsym= threshold = float(st) numerical = True - if str(given) == '' and not (str(expect) == ''): + if str(given) == '' and not str(expect) == '': return {'ok': False, 'msg': ''} try: @@ -125,12 +125,12 @@ def check(expect, given, numerical=False, matrix=False, normphase=False, abcsym= #msg += "dm = " + to_latex(dm) + " diff = " + str(abs(dm.vec().norm().evalf())) #msg += "expect = " + to_latex(xexpect) elif dosimplify: - if (sympy.simplify(xexpect) == sympy.simplify(xgiven)): + if sympy.simplify(xexpect) == sympy.simplify(xgiven): return {'ok': True, 'msg': msg} elif numerical: - if (abs((xexpect - xgiven).evalf(chop=True)) < threshold): + if abs((xexpect - xgiven).evalf(chop=True)) < threshold: return {'ok': True, 'msg': msg} - elif (xexpect == xgiven): + elif xexpect == xgiven: return {'ok': True, 'msg': msg} #msg += "

expect='%s', given='%s'" % (expect,given) # debugging @@ -149,9 +149,9 @@ def make_error_message(msg): def is_within_tolerance(expected, actual, tolerance): if expected == 0: - return (abs(actual) < tolerance) + return abs(actual) < tolerance else: - return (abs(abs(actual - expected) / expected) < tolerance) + return abs(abs(actual - expected) / expected) < tolerance #----------------------------------------------------------------------------- # Check function interface, which takes pmathml input @@ -198,10 +198,11 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None DEBUG = False # options - do_matrix = 'matrix' in (options or '') - do_qubit = 'qubit' in (options or '') - do_imaginary = 'imaginary' in (options or '') - do_numerical = 'numerical' in (options or '') + if options is None: + options = '' + do_matrix = 'matrix' in options + do_qubit = 'qubit' in options + do_numerical = 'numerical' in options # parse expected answer try: @@ -254,7 +255,7 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None fsym = f.sympy msg += '

You entered: %s

' % to_latex(f.sympy) except Exception, err: - log.exception("Error evaluating expression '%s' as a valid equation" % ans) + log.exception("Error evaluating expression '%s' as a valid equation", ans) msg += "

Error in evaluating your expression '%s' as a valid equation

" % (ans) if "Illegal math" in str(err): msg += "

Illegal math expression

" diff --git a/common/lib/xmodule/xmodule/abtest_module.py b/common/lib/xmodule/xmodule/abtest_module.py index 2a7bc5f0cb..a4b5ab48a6 100644 --- a/common/lib/xmodule/xmodule/abtest_module.py +++ b/common/lib/xmodule/xmodule/abtest_module.py @@ -80,6 +80,8 @@ class ABTestModule(ABTestFields, XModule): class ABTestDescriptor(ABTestFields, RawDescriptor, XmlDescriptor): module_class = ABTestModule + show_in_read_only_mode = True + @classmethod def definition_from_xml(cls, xml_object, system): """ diff --git a/common/lib/xmodule/xmodule/capa_base.py b/common/lib/xmodule/xmodule/capa_base.py index 579774c98a..604325fc21 100644 --- a/common/lib/xmodule/xmodule/capa_base.py +++ b/common/lib/xmodule/xmodule/capa_base.py @@ -143,9 +143,10 @@ class CapaFields(object): ) rerandomize = Randomization( display_name=_("Randomization"), - help=_("Defines how often inputs are randomized when a student loads the problem. " - "This setting only applies to problems that can have randomly generated numeric values. " - "A default value can be set in Advanced Settings."), + help=_( + 'Defines when to randomize the variables specified in the associated Python script. ' + 'For problems that do not randomize values, specify \"Never\". ' + ), default=RANDOMIZATION.NEVER, scope=Scope.settings, values=[ @@ -469,7 +470,7 @@ class CapaMixin(CapaFields): # If the problem is closed (and not a survey question with max_attempts==0), # then do NOT show the reset button. - if (self.closed() and not is_survey_question): + if self.closed() and not is_survey_question: return False # Button only shows up for randomized problems if the question has been submitted diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index e9c9a645d9..26ac4a4d17 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -119,6 +119,7 @@ class CapaDescriptor(CapaFields, RawDescriptor): module_class = CapaModule has_score = True + show_in_read_only_mode = True template_dir_name = 'problem' mako_template = "widgets/problem-edit.html" js = {'coffee': [resource_string(__name__, 'js/src/problem/edit.coffee')]} @@ -143,7 +144,7 @@ class CapaDescriptor(CapaFields, RawDescriptor): Show them only if use_latex_compiler is set to True in course settings. """ - return ('latex' not in template['template_id'] or course.use_latex_compiler) + return 'latex' not in template['template_id'] or course.use_latex_compiler def get_context(self): _context = RawDescriptor.get_context(self) diff --git a/common/lib/xmodule/xmodule/conditional_module.py b/common/lib/xmodule/xmodule/conditional_module.py index c887670a7a..a7453d3872 100644 --- a/common/lib/xmodule/xmodule/conditional_module.py +++ b/common/lib/xmodule/xmodule/conditional_module.py @@ -188,6 +188,8 @@ class ConditionalDescriptor(ConditionalFields, SequenceDescriptor): has_score = False + show_in_read_only_mode = True + def __init__(self, *args, **kwargs): """ Create an instance of the conditional module. diff --git a/common/lib/xmodule/xmodule/contentstore/content.py b/common/lib/xmodule/xmodule/contentstore/content.py index 31d70f6eec..544cef6b61 100644 --- a/common/lib/xmodule/xmodule/contentstore/content.py +++ b/common/lib/xmodule/xmodule/contentstore/content.py @@ -105,7 +105,7 @@ class StaticContent(object): if course_key is None: return None - assert(isinstance(course_key, CourseKey)) + assert isinstance(course_key, CourseKey) placeholder_id = uuid.uuid4().hex # create a dummy asset location with a fake but unique name. strip off the name, and return it url_path = StaticContent.serialize_asset_key_with_slash( diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index 91637abe0f..e5bf35b476 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -118,7 +118,7 @@ class Textbook(object): pass # Get the table of contents from S3 - log.info("Retrieving textbook table of contents from %s" % toc_url) + log.info("Retrieving textbook table of contents from %s", toc_url) try: r = requests.get(toc_url) except Exception as err: @@ -1009,7 +1009,7 @@ class CourseDescriptor(CourseFields, SequenceDescriptor, LicenseMixin): policy_str = grading_policy_file.read() # if we successfully read the file, stop looking at backups break - except (IOError): + except IOError: msg = "Unable to load course settings file from '{0}'".format(policy_path) log.warning(msg) diff --git a/common/lib/xmodule/xmodule/css/video/display.scss b/common/lib/xmodule/xmodule/css/video/display.scss index eb7ae84149..ad130c50e0 100644 --- a/common/lib/xmodule/xmodule/css/video/display.scss +++ b/common/lib/xmodule/xmodule/css/video/display.scss @@ -219,7 +219,7 @@ div.video { @extend %ui-fake-link; @include transition(none); display: block; - font-weight: 800; + font-weight: 700; line-height: 46px; margin: 0; padding: 0 0 0 15px; diff --git a/common/lib/xmodule/xmodule/discussion_module.py b/common/lib/xmodule/xmodule/discussion_module.py index 157f6141e2..8ae7f9ad93 100644 --- a/common/lib/xmodule/xmodule/discussion_module.py +++ b/common/lib/xmodule/xmodule/discussion_module.py @@ -4,7 +4,6 @@ from xmodule.x_module import XModule from xmodule.raw_module import RawDescriptor from xmodule.editing_module import MetadataOnlyEditingDescriptor from xblock.fields import String, Scope, UNIQUE_ID -from uuid import uuid4 # Make '_' a no-op so we can scrape strings _ = lambda text: text diff --git a/common/lib/xmodule/xmodule/foldit_module.py b/common/lib/xmodule/xmodule/foldit_module.py index de5957db94..67f3c93791 100644 --- a/common/lib/xmodule/xmodule/foldit_module.py +++ b/common/lib/xmodule/xmodule/foldit_module.py @@ -188,6 +188,8 @@ class FolditDescriptor(FolditFields, XmlDescriptor, EditingDescriptor): has_score = True + show_in_read_only_mode = True + js = {'coffee': [resource_string(__name__, 'js/src/html/edit.coffee')]} js_module_name = "HTMLEditingDescriptor" diff --git a/common/lib/xmodule/xmodule/graders.py b/common/lib/xmodule/xmodule/graders.py index 8d73738b28..64d2d76923 100644 --- a/common/lib/xmodule/xmodule/graders.py +++ b/common/lib/xmodule/xmodule/graders.py @@ -310,7 +310,7 @@ class AssignmentFormatGrader(CourseGrader): if index not in dropped_indices: aggregate_score += mark['percent'] - if (len(breakdown) - drop_count > 0): + if len(breakdown) - drop_count > 0: aggregate_score /= len(breakdown) - drop_count return aggregate_score, dropped_indices diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py index 8dcedfcc52..5bc086109b 100644 --- a/common/lib/xmodule/xmodule/html_module.py +++ b/common/lib/xmodule/xmodule/html_module.py @@ -96,6 +96,7 @@ class HtmlDescriptor(HtmlFields, XmlDescriptor, EditingDescriptor): # pylint: d filename_extension = "xml" template_dir_name = "html" has_responsive_ui = True + show_in_read_only_mode = True js = {'coffee': [resource_string(__name__, 'js/src/html/edit.coffee')]} js_module_name = "HTMLEditingDescriptor" @@ -135,7 +136,7 @@ class HtmlDescriptor(HtmlFields, XmlDescriptor, EditingDescriptor): # pylint: d Show them only if use_latex_compiler is set to True in course settings. """ - return ('latex' not in template['template_id'] or course.use_latex_compiler) + return 'latex' not in template['template_id'] or course.use_latex_compiler def get_context(self): """ diff --git a/common/lib/xmodule/xmodule/js/fixtures/video.html b/common/lib/xmodule/xmodule/js/fixtures/video.html index dabb3801b9..f7d04cce65 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video.html @@ -4,7 +4,7 @@
diff --git a/common/lib/xmodule/xmodule/js/fixtures/video_all.html b/common/lib/xmodule/xmodule/js/fixtures/video_all.html index 617d958357..5b20840630 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video_all.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video_all.html @@ -4,7 +4,7 @@
diff --git a/common/lib/xmodule/xmodule/js/fixtures/video_html5.html b/common/lib/xmodule/xmodule/js/fixtures/video_html5.html index 47be4f04fc..f82451e377 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video_html5.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video_html5.html @@ -4,7 +4,7 @@
diff --git a/common/lib/xmodule/xmodule/js/fixtures/video_no_captions.html b/common/lib/xmodule/xmodule/js/fixtures/video_no_captions.html index 77017d403d..267897e598 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video_no_captions.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video_no_captions.html @@ -4,7 +4,7 @@
diff --git a/common/lib/xmodule/xmodule/js/fixtures/video_with_bumper.html b/common/lib/xmodule/xmodule/js/fixtures/video_with_bumper.html index 22bd206268..efada9d13f 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video_with_bumper.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video_with_bumper.html @@ -4,7 +4,7 @@
diff --git a/common/lib/xmodule/xmodule/js/fixtures/video_yt_multiple.html b/common/lib/xmodule/xmodule/js/fixtures/video_yt_multiple.html index 8842b1e592..0af562049f 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video_yt_multiple.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video_yt_multiple.html @@ -4,7 +4,7 @@
@@ -38,7 +38,7 @@
@@ -68,7 +68,7 @@
diff --git a/common/lib/xmodule/xmodule/js/js_test.yml b/common/lib/xmodule/xmodule/js/js_test.yml index 6af10abaa5..6c72d4b649 100644 --- a/common/lib/xmodule/xmodule/js/js_test.yml +++ b/common/lib/xmodule/xmodule/js/js_test.yml @@ -59,6 +59,7 @@ lib_paths: - common_static/js/src/utility.js - public/js/split_test_staff.js - common_static/js/src/accessibility_tools.js + - common_static/js/vendor/moment.min.js # Paths to spec (test) JavaScript files spec_paths: diff --git a/common/lib/xmodule/xmodule/js/spec/helper.js b/common/lib/xmodule/xmodule/js/spec/helper.js index 97d422d5d8..9c83fd0063 100644 --- a/common/lib/xmodule/xmodule/js/spec/helper.js +++ b/common/lib/xmodule/xmodule/js/spec/helper.js @@ -36,7 +36,7 @@ return f(); } }; - + jasmine.YT = stubbedYT; // Stub YouTube API. window.YT = stubbedYT; @@ -76,19 +76,27 @@ jasmine.stubbedMetadata = { '7tqY6eQzVhE': { - id: '7tqY6eQzVhE', - duration: 300 + contentDetails : { + id: '7tqY6eQzVhE', + duration: 'PT5M0S' + } }, 'cogebirgzzM': { - id: 'cogebirgzzM', - duration: 200 + contentDetails : { + id: 'cogebirgzzM', + duration: 'PT3M20S' + } }, 'abcdefghijkl': { - id: 'abcdefghijkl', - duration: 400 + contentDetails : { + id: 'abcdefghijkl', + duration: 'PT6M40S' + } }, bogus: { - duration: 100 + contentDetails : { + duration: 'PT1M40S' + } } }; @@ -122,7 +130,7 @@ } return spy.andCallFake(function (settings) { var match = settings.url - .match(/youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/), + .match(/googleapis\.com\/.+\/videos\/\?id=(.+)&part=contentDetails/), status, callCallback; if (match) { status = match[1].split('_'); @@ -138,7 +146,7 @@ }; } else if (settings.success) { return settings.success({ - data: jasmine.stubbedMetadata[match[1]] + items: jasmine.stubbedMetadata[match[1]] }); } else { return { @@ -167,15 +175,6 @@ // Do nothing. return; } else if (settings.url === '/save_user_state') { - return {success: true}; - } else if (settings.url === 'http://www.youtube.com/iframe_api') { - // Stub YouTube API. - window.YT = stubbedYT; - - // Call the callback that must be called when YouTube API is - // loaded. By specification. - window.onYouTubeIframeAPIReady(); - return {success: true}; } else { throw 'External request attempted for ' + @@ -224,6 +223,19 @@ // Stub jQuery.scrollTo module. $.fn.scrollTo = jasmine.createSpy('jQuery.scrollTo'); + // Stub window.Video.loadYouTubeIFrameAPI() + window.Video.loadYouTubeIFrameAPI = jasmine.createSpy('window.Video.loadYouTubeIFrameAPI').andReturn( + function (scriptTag) { + var event = document.createEvent('Event'); + if (fixture === "video.html") { + event.initEvent('load', false, false); + } else { + event.initEvent('error', false, false); + } + scriptTag.dispatchEvent(event); + } + ); + jasmine.initializePlayer = function (fixture, params) { var state; diff --git a/common/lib/xmodule/xmodule/js/spec/video/general_spec.js b/common/lib/xmodule/xmodule/js/spec/video/general_spec.js index 7cefab5e49..f9c0eabf2d 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/general_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/general_spec.js @@ -115,6 +115,12 @@ return state.youtubeApiAvailable === true; }, 'YouTube API is loaded', 3000); + window.YT = jasmine.YT; + + // Call the callback that must be called when YouTube API is + // loaded. By specification. + window.onYouTubeIframeAPIReady(); + runs(function () { // If YouTube API is not loaded, then the code will should create // a global callback that will be called by API once it is loaded. diff --git a/common/lib/xmodule/xmodule/js/spec/video/initialize_spec.js b/common/lib/xmodule/xmodule/js/spec/video/initialize_spec.js index f3194b8bce..0404005144 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/initialize_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/initialize_spec.js @@ -71,10 +71,10 @@ function (Initialize) { speed: '1.50', metadata: { 'testId': { - duration: 400 + duration: 'PT6M40S' }, 'videoId': { - duration: 100 + duration: 'PT1M40S' } }, videos: { diff --git a/common/lib/xmodule/xmodule/js/src/video/01_initialize.js b/common/lib/xmodule/xmodule/js/src/video/01_initialize.js index 2a30ceb454..cc43a23356 100644 --- a/common/lib/xmodule/xmodule/js/src/video/01_initialize.js +++ b/common/lib/xmodule/xmodule/js/src/video/01_initialize.js @@ -16,6 +16,8 @@ define( 'video/01_initialize.js', ['video/03_video_player.js', 'video/00_i18n.js'], function (VideoPlayer, i18n) { + var moment = window.moment; + /** * @function * @@ -31,6 +33,9 @@ function (VideoPlayer, i18n) { state.initialize(element) .done(function () { + if (state.isYoutubeType()) { + state.parseSpeed(); + } // On iPhones and iPods native controls are used. if (/iP(hone|od)/i.test(state.isTouch[0])) { _hideWaitPlaceholder(state); @@ -75,7 +80,10 @@ function (VideoPlayer, i18n) { setSpeed: setSpeed, speedToString: speedToString, trigger: trigger, - youtubeId: youtubeId + youtubeId: youtubeId, + loadHtmlPlayer: loadHtmlPlayer, + loadYoutubePlayer: loadYoutubePlayer, + loadYouTubeIFrameAPI: loadYouTubeIFrameAPI }, _youtubeApiDeferred = null, @@ -126,6 +134,9 @@ function (VideoPlayer, i18n) { onYTApiReady = function () { console.log('[Video info]: YouTube API is available and is loaded.'); + if (state.htmlPlayerLoaded) { return; } + + console.log('[Video info]: Starting YouTube player.'); video = VideoPlayer(state); state.modules.push(video); @@ -176,7 +187,6 @@ function (VideoPlayer, i18n) { if (!_youtubeApiDeferred) { _youtubeApiDeferred = $.Deferred(); setupOnYouTubeIframeAPIReady(); - _loadYoutubeApi(state); } else if (!window.onYouTubeIframeAPIReady || !window.onYouTubeIframeAPIReady.done) { // The Deferred object could have been already defined in a previous // initialization of the video module. However, since then the global variable @@ -196,24 +206,32 @@ function (VideoPlayer, i18n) { state.modules.push(video); state.__dfd__.resolve(); + state.htmlPlayerLoaded = true; } } - function _loadYoutubeApi(state) { - console.log('[Video info]: YouTube API is not loaded. Will try to load...'); + function _waitForYoutubeApi(state) { + console.log('[Video info]: Starting to wait for YouTube API to load.'); window.setTimeout(function () { // If YouTube API will load OK, it will run `onYouTubeIframeAPIReady` // callback, which will set `state.youtubeApiAvailable` to `true`. // If something goes wrong at this stage, `state.youtubeApiAvailable` is // `false`. - if (!state.youtubeIsAvailable) { + if (!state.youtubeApiAvailable) { console.log('[Video info]: YouTube API is not available.'); + if (!state.htmlPlayerLoaded) { + state.loadHtmlPlayer(); + } } - state.el.trigger('youtube_availability', [state.youtubeIsAvailable]); + state.el.trigger('youtube_availability', [state.youtubeApiAvailable]); }, state.config.ytTestTimeout); - $.getScript(document.location.protocol + '//' + state.config.ytApiUrl); + } + + function loadYouTubeIFrameAPI(scriptTag) { + var firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag); } // function _configureCaptions(state) @@ -454,6 +472,50 @@ function (VideoPlayer, i18n) { }); } + function loadYoutubePlayer() { + if (this.htmlPlayerLoaded) { return; } + + console.log( + '[Video info]: Fetch metadata for YouTube video.' + ); + + this.fetchMetadata(); + this.parseSpeed(); + } + + function loadHtmlPlayer() { + + // When the youtube link doesn't work for any reason + // (for example, firewall) any + // alternate sources should automatically play. + if (!_prepareHTML5Video(this)) { + console.log( + '[Video info]: Continue loading ' + + 'YouTube video.' + ); + + // Non-YouTube sources were not found either. + + this.el.find('.video-player div') + .removeClass('hidden'); + this.el.find('.video-player h3') + .addClass('hidden'); + + // If in reality the timeout was to short, try to + // continue loading the YouTube video anyways. + this.loadYoutubePlayer(); + } else { + console.log( + '[Video info]: Start HTML5 player.' + ); + + // In-browser HTML5 player does not support quality + // control. + this.el.find('a.quality_control').hide(); + _renderElements(this); + } + } + // function initialize(element) // The function set initial configuration and preparation. @@ -484,7 +546,7 @@ function (VideoPlayer, i18n) { // jQuery .data() return object with keys in lower camelCase format. this.config = $.extend({}, _getConfiguration(this.metadata, this.storage), { element: element, - fadeOutTimeout: 1400, + fadeOutTimeout: 1400, captionsFreezeTime: 10000, mode: $.cookie('edX_video_player_mode'), // Available HD qualities will only be accessible once the video has @@ -500,6 +562,9 @@ function (VideoPlayer, i18n) { this.speed = this.speedToString( this.config.speed || this.config.generalSpeed ); + this.htmlPlayerLoaded = false; + + _setConfigurations(this); if (!(_parseYouTubeIDs(this))) { @@ -512,67 +577,30 @@ function (VideoPlayer, i18n) { } console.log('[Video info]: Start player in HTML5 mode.'); - - _setConfigurations(this); _renderElements(this); } else { - if (!this.youtubeXhr) { - this.youtubeXhr = this.getVideoMetadata(); - } + _renderElements(this); - this.youtubeXhr - .always(function (json, status) { - // It will work for both if statusCode is 200 or 410. - var didSucceed = (json.error && json.error.code === 410) || status === 'success' || status === 'notmodified'; - if (!didSucceed) { - console.log( - '[Video info]: YouTube returned an error for ' + - 'video with id "' + id + '".' - ); + _waitForYoutubeApi(this); - // When the youtube link doesn't work for any reason - // (for example, the great firewall in china) any - // alternate sources should automatically play. - if (!_prepareHTML5Video(self)) { - console.log( - '[Video info]: Continue loading ' + - 'YouTube video.' - ); + var scriptTag = document.createElement('script'); - // Non-YouTube sources were not found either. + scriptTag.src = this.config.ytApiUrl; + scriptTag.async = true; - el.find('.video-player div') - .removeClass('hidden'); - el.find('.video-player h3') - .addClass('hidden'); + $(scriptTag).on('load', function() { + self.loadYoutubePlayer(); + }); + $(scriptTag).on('error', function() { + console.log( + '[Video info]: YouTube returned an error for ' + + 'video with id "' + self.id + '".' + ); + self.loadHtmlPlayer(); + }); - // If in reality the timeout was to short, try to - // continue loading the YouTube video anyways. - self.fetchMetadata(); - self.parseSpeed(); - } else { - console.log( - '[Video info]: Change player mode to HTML5.' - ); - - // In-browser HTML5 player does not support quality - // control. - el.find('a.quality_control').hide(); - } - } else { - console.log( - '[Video info]: Start player in YouTube mode.' - ); - - self.fetchMetadata(); - self.parseSpeed(); - } - - _setConfigurations(self); - _renderElements(self); - }); + window.Video.loadYouTubeIFrameAPI(scriptTag); } - return __dfd__.promise(); } @@ -619,8 +647,9 @@ function (VideoPlayer, i18n) { metadataXHRs = _.map(this.videos, function (url, speed) { return self.getVideoMetadata(url, function (data) { - if (data.data) { - self.metadata[data.data.id] = data.data; + if (data.items.length > 0) { + var metaDataItem = data.items[0]; + self.metadata[metaDataItem.id] = metaDataItem.contentDetails; } }); }); @@ -671,16 +700,16 @@ function (VideoPlayer, i18n) { if (!(_.isString(url))) { url = this.videos['1.0'] || ''; } - - return $.ajax({ - url: [ - document.location.protocol, '//', this.config.ytTestUrl, url, - '?v=2&alt=jsonc' - ].join(''), - dataType: 'jsonp', - timeout: this.config.ytTestTimeout, - success: _.isFunction(callback) ? callback : null - }); + // Will hit the API URL iF YT key is defined in settings. + if (this.config.ytKey) { + return $.ajax({ + url: [this.config.ytMetadataUrl, '?id=', url, '&part=contentDetails&key=', this.config.ytKey].join(''), + timeout: this.config.ytTestTimeout, + success: _.isFunction(callback) ? callback : null + }); + } else { + return $.Deferred().reject().promise(); + } } function youtubeId(speed) { @@ -693,7 +722,7 @@ function (VideoPlayer, i18n) { function getDuration() { try { - return this.metadata[this.youtubeId()].duration; + return moment.duration(this.metadata[this.youtubeId()].duration, moment.ISO_8601).asSeconds(); } catch (err) { return _.result(this.metadata[this.youtubeId('1.0')], 'duration') || 0; } diff --git a/common/lib/xmodule/xmodule/js/src/video/10_main.js b/common/lib/xmodule/xmodule/js/src/video/10_main.js index be3bbc8ae8..23763aaf1c 100644 --- a/common/lib/xmodule/xmodule/js/src/video/10_main.js +++ b/common/lib/xmodule/xmodule/js/src/video/10_main.js @@ -160,6 +160,8 @@ youtubeXhr = null; }; + window.Video.loadYouTubeIFrameAPI = initialize.prototype.loadYouTubeIFrameAPI; + // Invoke the mock Video constructor so that the elements stored within it can be processed by the real // `window.Video` constructor. oldVideo(null, true); diff --git a/common/lib/xmodule/xmodule/library_content_module.py b/common/lib/xmodule/xmodule/library_content_module.py index fb2723b880..cea8dd55b7 100644 --- a/common/lib/xmodule/xmodule/library_content_module.py +++ b/common/lib/xmodule/xmodule/library_content_module.py @@ -299,6 +299,8 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe js = {'coffee': [resource_string(__name__, 'js/src/vertical/edit.coffee')]} js_module_name = "VerticalDescriptor" + show_in_read_only_mode = True + @property def non_editable_metadata_fields(self): non_editable_fields = super(LibraryContentDescriptor, self).non_editable_metadata_fields diff --git a/common/lib/xmodule/xmodule/modulestore/__init__.py b/common/lib/xmodule/xmodule/modulestore/__init__.py index c511aa9b32..3017f99d19 100644 --- a/common/lib/xmodule/xmodule/modulestore/__init__.py +++ b/common/lib/xmodule/xmodule/modulestore/__init__.py @@ -1151,7 +1151,7 @@ class ModuleStoreReadBase(BulkOperationsMixin, ModuleStoreRead): # pylint: disable=fixme # TODO (vshnayder): post-launch, make errors properties of items # self.get_item(location) - assert(isinstance(course_key, CourseKey)) + assert isinstance(course_key, CourseKey) return self._course_errors[course_key].errors def get_errored_courses(self): @@ -1169,7 +1169,7 @@ class ModuleStoreReadBase(BulkOperationsMixin, ModuleStoreRead): Default impl--linear search through course list """ - assert(isinstance(course_id, CourseKey)) + assert isinstance(course_id, CourseKey) for course in self.get_courses(**kwargs): if course.id == course_id: return course @@ -1184,7 +1184,7 @@ class ModuleStoreReadBase(BulkOperationsMixin, ModuleStoreRead): to search for whether a potentially conflicting course exists in that case. """ # linear search through list - assert(isinstance(course_id, CourseKey)) + assert isinstance(course_id, CourseKey) if ignore_case: return next( ( @@ -1353,7 +1353,7 @@ class ModuleStoreWriteBase(ModuleStoreReadBase, ModuleStoreWrite): otherwise a publish will be signalled at the end of the bulk operation Arguments: - library_updated - library_updated to which the signal applies + library_key - library_key to which the signal applies """ signal_handler = getattr(self, 'signal_handler', None) if signal_handler: @@ -1363,6 +1363,14 @@ class ModuleStoreWriteBase(ModuleStoreReadBase, ModuleStoreWrite): else: signal_handler.send("library_updated", library_key=library_key) + def _emit_course_deleted_signal(self, course_key): + """ + Helper method used to emit the course_deleted signal. + """ + signal_handler = getattr(self, 'signal_handler', None) + if signal_handler: + signal_handler.send("course_deleted", course_key=course_key) + def only_xmodules(identifier, entry_points): """Only use entry_points that are supplied by the xmodule package""" diff --git a/common/lib/xmodule/xmodule/modulestore/django.py b/common/lib/xmodule/xmodule/modulestore/django.py index 8c631a75ae..8b91916b45 100644 --- a/common/lib/xmodule/xmodule/modulestore/django.py +++ b/common/lib/xmodule/xmodule/modulestore/django.py @@ -87,11 +87,13 @@ class SignalHandler(object): do the actual work. """ course_published = django.dispatch.Signal(providing_args=["course_key"]) + course_deleted = django.dispatch.Signal(providing_args=["course_key"]) library_updated = django.dispatch.Signal(providing_args=["library_key"]) _mapping = { "course_published": course_published, - "library_updated": library_updated + "course_deleted": course_deleted, + "library_updated": library_updated, } def __init__(self, modulestore_class): diff --git a/common/lib/xmodule/xmodule/modulestore/inheritance.py b/common/lib/xmodule/xmodule/modulestore/inheritance.py index b011807df3..782d3fefc1 100644 --- a/common/lib/xmodule/xmodule/modulestore/inheritance.py +++ b/common/lib/xmodule/xmodule/modulestore/inheritance.py @@ -98,7 +98,12 @@ class InheritanceMixin(XBlockMixin): ) rerandomize = String( display_name=_("Randomization"), - help=_("Specify how often variable values in a problem are randomized when a student loads the problem. Valid values are \"always\", \"onreset\", \"never\", and \"per_student\". This setting only applies to problems that have randomly generated numeric values."), + help=_( + 'Specify the default for how often variable values in a problem are randomized. ' + 'This setting should be set to \"never\" unless you plan to provide a Python ' + 'script to identify and randomize values in most of the problems in your course. ' + 'Valid values are \"always\", \"onreset\", \"never\", and \"per_student\".' + ), scope=Scope.settings, default="never", ) diff --git a/common/lib/xmodule/xmodule/modulestore/mixed.py b/common/lib/xmodule/xmodule/modulestore/mixed.py index 65bb345e1d..a49c7dbd9a 100644 --- a/common/lib/xmodule/xmodule/modulestore/mixed.py +++ b/common/lib/xmodule/xmodule/modulestore/mixed.py @@ -280,6 +280,21 @@ 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): """ diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py index 8c181b2639..6e6335d3bd 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py @@ -167,6 +167,8 @@ class DraftModuleStore(MongoModuleStore): self.collection.remove(course_query, multi=True) self.delete_all_asset_metadata(course_key, user_id) + self._emit_course_deleted_signal(course_key) + def clone_course(self, source_course_id, dest_course_id, user_id, fields=None, **kwargs): """ Only called if cloning within this store or if env doesn't set up mixed. diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py index 5ac0a50faf..3a829212c0 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py @@ -1495,7 +1495,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase): partitioned_fields = self.partition_fields_by_scope(block_type, fields) new_def_data = partitioned_fields.get(Scope.content, {}) # persist the definition if persisted != passed - if (definition_locator is None or isinstance(definition_locator.definition_id, LocalId)): + if definition_locator is None or isinstance(definition_locator.definition_id, LocalId): definition_locator = self.create_definition_from_data(course_key, new_def_data, block_type, user_id) elif new_def_data: definition_locator, _ = self.update_definition_from_data(course_key, definition_locator, new_def_data, user_id) @@ -2443,6 +2443,8 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase): # in case the course is later restored. # super(SplitMongoModuleStore, self).delete_course(course_key, user_id) + self._emit_course_deleted_signal(course_key) + @contract(block_map="dict(BlockKey: dict)", block_key=BlockKey) def inherit_settings( self, block_map, block_key, inherited_settings_map, inheriting_settings=None, inherited_from=None @@ -2770,7 +2772,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase): course_key.version_guid is None or index_entry['versions'][course_key.branch] == course_key.version_guid ) - if (is_head or force): + if is_head or force: return index_entry else: raise VersionConflictError( diff --git a/common/lib/xmodule/xmodule/modulestore/tests/factories.py b/common/lib/xmodule/xmodule/modulestore/tests/factories.py index abfc1f9664..df5de468b0 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/factories.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/factories.py @@ -3,8 +3,6 @@ Factories for use in tests of XBlocks. """ import functools -import inspect -import pprint import pymongo.message import threading import traceback @@ -14,7 +12,7 @@ from uuid import uuid4 from factory import Factory, Sequence, lazy_attribute_sequence, lazy_attribute from factory.containers import CyclicDefinitionError -from mock import Mock, patch +from mock import patch from nose.tools import assert_less_equal, assert_greater_equal import dogstats_wrapper as dog_stats_api diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py index 4ed6aa7c00..74aa23066b 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py @@ -8,7 +8,6 @@ import logging import ddt import itertools import mimetypes -from unittest import skip from uuid import uuid4 from contextlib import contextmanager from mock import patch @@ -1408,7 +1407,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup): course_id.make_usage_key('course_info', 'updates'), ] - for location in (orphan_locations + detached_locations): + for location in orphan_locations + detached_locations: self.store.create_item( self.user_id, location.course_key, @@ -2415,6 +2414,34 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup): self.assertEqual(receiver.call_count, 0) self.assertEqual(receiver.call_count, 0) + @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) + def test_course_deleted_signal(self, default): + with MongoContentstoreBuilder().build() as contentstore: + self.store = MixedModuleStore( + contentstore=contentstore, + create_modulestore_instance=create_modulestore_instance, + mappings={}, + signal_handler=SignalHandler(MixedModuleStore), + **self.OPTIONS + ) + self.addCleanup(self.store.close_all_connections) + + with self.store.default_store(default): + self.assertIsNotNone(self.store.thread_cache.default_store.signal_handler) + + with mock_signal_receiver(SignalHandler.course_deleted) as receiver: + self.assertEqual(receiver.call_count, 0) + + # Create a course + course = self.store.create_course('org_x', 'course_y', 'run_z', self.user_id) + course_key = course.id + + # Delete the course + course = self.store.delete_course(course_key, self.user_id) + + # Verify that the signal was emitted + self.assertEqual(receiver.call_count, 1) + @ddt.ddt @attr('mongo') diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py b/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py index c39bbf4534..ad7c9ef989 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py @@ -3,7 +3,6 @@ Tests for XML importer. """ import mock from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator -from xblock.core import XBlock from xblock.fields import String, Scope, ScopeIds, List from xblock.runtime import Runtime, KvsFieldData, DictKeyValueStore from xmodule.x_module import XModuleMixin diff --git a/common/lib/xmodule/xmodule/modulestore/xml.py b/common/lib/xmodule/xmodule/modulestore/xml.py index 8950380615..6dd2fec98d 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml.py +++ b/common/lib/xmodule/xmodule/modulestore/xml.py @@ -866,7 +866,7 @@ class XMLModuleStore(ModuleStoreReadBase): :return: list of course locations """ courses = self.get_courses() - return [course.location.course_key for course in courses if (course.wiki_slug == wiki_slug)] + return [course.location.course_key for course in courses if course.wiki_slug == wiki_slug] def heartbeat(self): """ diff --git a/common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py b/common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py index fb459e0f91..b57d253e72 100644 --- a/common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py +++ b/common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py @@ -298,7 +298,7 @@ class OpenEndedChild(object): def _allow_reset(self): """Can the module be reset?""" - return (self.child_state == self.DONE and self.child_attempts < self.max_attempts) + return self.child_state == self.DONE and self.child_attempts < self.max_attempts def max_score(self): """ @@ -396,7 +396,7 @@ class OpenEndedChild(object): @return: Boolean correct. """ correct = False - if (isinstance(score, (int, long, float, complex))): + if isinstance(score, (int, long, float, complex)): score_ratio = int(score) / float(self.max_score()) correct = (score_ratio >= 0.66) return correct diff --git a/common/lib/xmodule/xmodule/peer_grading_module.py b/common/lib/xmodule/xmodule/peer_grading_module.py index 5a5532583c..c414c8a261 100644 --- a/common/lib/xmodule/xmodule/peer_grading_module.py +++ b/common/lib/xmodule/xmodule/peer_grading_module.py @@ -118,7 +118,7 @@ class PeerGradingModule(PeerGradingFields, XModule): # We need to set the location here so the child modules can use it. self.runtime.set('location', self.location) - if (self.runtime.open_ended_grading_interface): + if self.runtime.open_ended_grading_interface: self.peer_gs = PeerGradingService(self.system.open_ended_grading_interface, self.system.render_template) else: self.peer_gs = MockPeerGradingService() diff --git a/common/lib/xmodule/xmodule/randomize_module.py b/common/lib/xmodule/xmodule/randomize_module.py index 3973bdffbf..a41cad983c 100644 --- a/common/lib/xmodule/xmodule/randomize_module.py +++ b/common/lib/xmodule/xmodule/randomize_module.py @@ -101,6 +101,8 @@ class RandomizeDescriptor(RandomizeFields, SequenceDescriptor): filename_extension = "xml" + show_in_read_only_mode = True + def definition_to_xml(self, resource_fs): xml_object = etree.Element('randomize') diff --git a/common/lib/xmodule/xmodule/seq_module.py b/common/lib/xmodule/xmodule/seq_module.py index 0cbaaac589..e3fe56c646 100644 --- a/common/lib/xmodule/xmodule/seq_module.py +++ b/common/lib/xmodule/xmodule/seq_module.py @@ -157,6 +157,8 @@ class SequenceDescriptor(SequenceFields, MakoModuleDescriptor, XmlDescriptor): mako_template = 'widgets/sequence-edit.html' module_class = SequenceModule + show_in_read_only_mode = True + js = { 'coffee': [resource_string(__name__, 'js/src/sequence/edit.coffee')], } diff --git a/common/lib/xmodule/xmodule/split_test_module.py b/common/lib/xmodule/xmodule/split_test_module.py index c862817f58..82127fdda8 100644 --- a/common/lib/xmodule/xmodule/split_test_module.py +++ b/common/lib/xmodule/xmodule/split_test_module.py @@ -375,6 +375,8 @@ class SplitTestDescriptor(SplitTestFields, SequenceDescriptor, StudioEditableDes mako_template = "widgets/metadata-only-edit.html" + show_in_read_only_mode = True + child_descriptor = module_attr('child_descriptor') log_child_render = module_attr('log_child_render') get_content_titles = module_attr('get_content_titles') diff --git a/common/lib/xmodule/xmodule/tabs.py b/common/lib/xmodule/xmodule/tabs.py index 8671d715cd..065f71e22b 100644 --- a/common/lib/xmodule/xmodule/tabs.py +++ b/common/lib/xmodule/xmodule/tabs.py @@ -146,7 +146,7 @@ class CourseTab(object): """ Overrides the not equal operator as a partner to the equal operator. """ - return not (self == other) + return not self == other @classmethod def validate(cls, tab_dict, raise_error=True): diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py index 33b0e9fe6f..16ca6c6fb0 100644 --- a/common/lib/xmodule/xmodule/tests/test_capa_module.py +++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py @@ -63,7 +63,7 @@ class CapaFactory(object): """ Return the input key to use when passing GET parameters """ - return ("input_" + cls.answer_key(response_num, input_num)) + return "input_" + cls.answer_key(response_num, input_num) @classmethod def answer_key(cls, response_num=2, input_num=1): diff --git a/common/lib/xmodule/xmodule/tests/test_course_module.py b/common/lib/xmodule/xmodule/tests/test_course_module.py index da05da360e..db594abe09 100644 --- a/common/lib/xmodule/xmodule/tests/test_course_module.py +++ b/common/lib/xmodule/xmodule/tests/test_course_module.py @@ -241,25 +241,25 @@ class IsNewCourseTestCase(unittest.TestCase): def test_is_newish(self): descriptor = get_dummy_course(start='2012-12-02T12:00', is_new=True) - assert(descriptor.is_newish is True) + assert descriptor.is_newish is True descriptor = get_dummy_course(start='2013-02-02T12:00', is_new=False) - assert(descriptor.is_newish is False) + assert descriptor.is_newish is False descriptor = get_dummy_course(start='2013-02-02T12:00', is_new=True) - assert(descriptor.is_newish is True) + assert descriptor.is_newish is True descriptor = get_dummy_course(start='2013-01-15T12:00') - assert(descriptor.is_newish is True) + assert descriptor.is_newish is True descriptor = get_dummy_course(start='2013-03-01T12:00') - assert(descriptor.is_newish is True) + assert descriptor.is_newish is True descriptor = get_dummy_course(start='2012-10-15T12:00') - assert(descriptor.is_newish is False) + assert descriptor.is_newish is False descriptor = get_dummy_course(start='2012-12-31T12:00') - assert(descriptor.is_newish is True) + assert descriptor.is_newish is True def test_end_date_text(self): # No end date set, returns empty string. diff --git a/common/lib/xmodule/xmodule/tests/test_delay_between_attempts.py b/common/lib/xmodule/xmodule/tests/test_delay_between_attempts.py index 7deabf8756..1b400269de 100644 --- a/common/lib/xmodule/xmodule/tests/test_delay_between_attempts.py +++ b/common/lib/xmodule/xmodule/tests/test_delay_between_attempts.py @@ -58,7 +58,7 @@ class CapaFactoryWithDelay(object): """ Return the input key to use when passing GET parameters """ - return ("input_" + cls.answer_key(input_num)) + return "input_" + cls.answer_key(input_num) @classmethod def answer_key(cls, input_num=2): diff --git a/common/lib/xmodule/xmodule/tests/test_video.py b/common/lib/xmodule/xmodule/tests/test_video.py index 269adf6109..5b0ae3b2fe 100644 --- a/common/lib/xmodule/xmodule/tests/test_video.py +++ b/common/lib/xmodule/xmodule/tests/test_video.py @@ -736,8 +736,8 @@ class VideoDescriptorIndexingTestCase(unittest.TestCase): # YouTube JavaScript API 'API': 'www.youtube.com/iframe_api', - # URL to test YouTube availability - 'TEST_URL': 'gdata.youtube.com/feeds/api/videos/', + # URL to get YouTube metadata + 'METADATA_URL': 'www.googleapis.com/youtube/v3/videos/', # Current youtube api for requesting transcripts. # For example: http://video.google.com/timedtext?lang=en&v=j_jEn79vS3g. diff --git a/common/lib/xmodule/xmodule/vertical_block.py b/common/lib/xmodule/xmodule/vertical_block.py index 1f2b4b874f..62af97c66c 100644 --- a/common/lib/xmodule/xmodule/vertical_block.py +++ b/common/lib/xmodule/xmodule/vertical_block.py @@ -29,6 +29,8 @@ class VerticalBlock(SequenceFields, XModuleFields, StudioEditableBlock, XmlParse has_children = True + show_in_read_only_mode = True + def student_view(self, context): """ Renders the student view of the block in the LMS. diff --git a/common/lib/xmodule/xmodule/video_module/transcripts_utils.py b/common/lib/xmodule/xmodule/video_module/transcripts_utils.py index bf7d39b7c9..53b15a49a5 100644 --- a/common/lib/xmodule/xmodule/video_module/transcripts_utils.py +++ b/common/lib/xmodule/xmodule/video_module/transcripts_utils.py @@ -462,7 +462,7 @@ def get_or_create_sjson(item, transcripts): source_subs_id, result_subs_dict = user_subs_id, {1.0: user_subs_id} try: sjson_transcript = Transcript.asset(item.location, source_subs_id, item.transcript_language).data - except (NotFoundError): # generating sjson from srt + except NotFoundError: # generating sjson from srt generate_sjson_for_all_speeds(item, user_filename, result_subs_dict, item.transcript_language) sjson_transcript = Transcript.asset(item.location, source_subs_id, item.transcript_language).data return sjson_transcript diff --git a/common/lib/xmodule/xmodule/video_module/video_handlers.py b/common/lib/xmodule/xmodule/video_module/video_handlers.py index 0438c15f71..1f19f86b96 100644 --- a/common/lib/xmodule/xmodule/video_module/video_handlers.py +++ b/common/lib/xmodule/xmodule/video_module/video_handlers.py @@ -125,7 +125,7 @@ class VideoStudentViewHandlers(object): try: sjson_transcript = Transcript.asset(self.location, youtube_id, self.transcript_language).data - except (NotFoundError): + except NotFoundError: log.info("Can't find content in storage for %s transcript: generating.", youtube_id) generate_sjson_for_all_speeds( self, diff --git a/common/lib/xmodule/xmodule/video_module/video_module.py b/common/lib/xmodule/xmodule/video_module/video_module.py index f9134c820c..6e93accb98 100644 --- a/common/lib/xmodule/xmodule/video_module/video_module.py +++ b/common/lib/xmodule/xmodule/video_module/video_module.py @@ -86,6 +86,7 @@ log = logging.getLogger(__name__) _ = lambda text: text +@XBlock.wants('settings') class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers, XModule, LicenseMixin): """ XML source example: @@ -261,6 +262,15 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers, cdn_exp_group = None self.youtube_streams = youtube_streams or create_youtube_string(self) # pylint: disable=W0201 + + settings_service = self.runtime.service(self, 'settings') + + yt_api_key = None + if settings_service: + xblock_settings = settings_service.get_settings_bucket(self) + if xblock_settings and 'YOUTUBE_API_KEY' in xblock_settings: + yt_api_key = xblock_settings['YOUTUBE_API_KEY'] + metadata = { 'saveStateUrl': self.system.ajax_url + '/save_user_state', 'autoplay': settings.FEATURES.get('AUTOPLAY_VIDEOS', False), @@ -286,7 +296,9 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers, 'ytTestTimeout': 1500, 'ytApiUrl': settings.YOUTUBE['API'], - 'ytTestUrl': settings.YOUTUBE['TEST_URL'], + 'ytMetadataUrl': settings.YOUTUBE['METADATA_URL'], + 'ytKey': yt_api_key, + 'transcriptTranslationUrl': self.runtime.handler_url( self, 'transcript', 'translation/__lang__' ).rstrip('/?'), @@ -339,6 +351,8 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler module_class = VideoModule transcript = module_attr('transcript') + show_in_read_only_mode = True + tabs = [ { 'name': _("Basic"), diff --git a/common/lib/xmodule/xmodule/video_module/video_xfields.py b/common/lib/xmodule/xmodule/video_module/video_xfields.py index 65421fa905..a10434d785 100644 --- a/common/lib/xmodule/xmodule/video_module/video_xfields.py +++ b/common/lib/xmodule/xmodule/video_module/video_xfields.py @@ -6,7 +6,6 @@ import datetime from xblock.fields import Scope, String, Float, Boolean, List, Dict, DateTime from xmodule.fields import RelativeTime -from xmodule.mixin import LicenseMixin # Make '_' a no-op so we can scrape strings _ = lambda text: text diff --git a/common/lib/xmodule/xmodule/wrapper_module.py b/common/lib/xmodule/xmodule/wrapper_module.py index 622fbd28e7..63e132716d 100644 --- a/common/lib/xmodule/xmodule/wrapper_module.py +++ b/common/lib/xmodule/xmodule/wrapper_module.py @@ -2,7 +2,6 @@ # But w/o css delimiters between children from xmodule.vertical_block import VerticalBlock -from pkg_resources import resource_string # HACK: This shouldn't be hard-coded to two types # OBSOLETE: This obsoletes 'type' diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 4943b2610e..2f55f57a41 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -278,6 +278,10 @@ class XModuleMixin(XModuleFields, XBlock): # (like a practice problem). has_score = False + # Whether this module can be displayed in read-only mode. It is safe to set this to True if + # all user state is handled through the FieldData API. + show_in_read_only_mode = False + # Class level variable # True if this descriptor always requires recalculation of grades, for @@ -371,7 +375,7 @@ class XModuleMixin(XModuleFields, XBlock): """ result = {} for field in self.fields.values(): - if (field.scope == scope and field.is_set_on(self)): + if field.scope == scope and field.is_set_on(self): result[field.name] = field.read_json(self) return result @@ -760,6 +764,7 @@ class XModule(HTMLSnippet, XModuleMixin): # pylint: disable=abstract-method entry_point = "xmodule.v1" has_score = descriptor_attr('has_score') + show_in_read_only_mode = descriptor_attr('show_in_read_only_mode') _field_data_cache = descriptor_attr('_field_data_cache') _field_data = descriptor_attr('_field_data') _dirty_fields = descriptor_attr('_dirty_fields') diff --git a/cms/static/js/factories/common_deps.js b/common/static/common/js/common_libraries.js similarity index 82% rename from cms/static/js/factories/common_deps.js rename to common/static/common/js/common_libraries.js index ded2bed352..1e935d6821 100644 --- a/cms/static/js/factories/common_deps.js +++ b/common/static/common/js/common_libraries.js @@ -1 +1 @@ -define(['domReady!', 'jquery', 'backbone', 'underscore', 'gettext', 'text']); +define(['domReady!', 'jquery', 'backbone', 'underscore', 'gettext']); diff --git a/common/static/common/js/components/views/paginated_view.js b/common/static/common/js/components/views/paginated_view.js new file mode 100644 index 0000000000..b90213ab59 --- /dev/null +++ b/common/static/common/js/components/views/paginated_view.js @@ -0,0 +1,43 @@ +;(function(define) { + 'use strict'; + define([ + 'backbone', + 'underscore', + 'common/js/components/views/paging_header', + 'common/js/components/views/paging_footer', + 'common/js/components/views/list', + 'text!common/templates/components/paginated-view.underscore' + ], function (Backbone, _, PagingHeader, PagingFooter, ListView, paginatedViewTemplate) { + var PaginatedView = Backbone.View.extend({ + initialize: function () { + var ItemListView = ListView.extend({ + tagName: 'div', + className: this.type + '-container', + itemViewClass: this.itemViewClass + }); + this.listView = new ItemListView({collection: this.options.collection}); + this.headerView = this.headerView = new PagingHeader({collection: this.options.collection}); + this.footerView = new PagingFooter({ + collection: this.options.collection, hideWhenOnePage: true + }); + this.collection.on('page_changed', function () { + this.$('.sr-is-focusable.sr-' + this.type + '-view').focus(); + }, this); + }, + + render: function () { + this.$el.html(_.template(paginatedViewTemplate, {type: this.type})); + this.assign(this.listView, '.' + this.type + '-list'); + this.assign(this.headerView, '.' + this.type + '-paging-header'); + this.assign(this.footerView, '.' + this.type + '-paging-footer'); + return this; + }, + + assign: function (view, selector) { + view.setElement(this.$(selector)).render(); + } + }); + + return PaginatedView; + }); +}).call(this, define || RequireJS.define); diff --git a/common/static/common/js/components/views/paging_footer.js b/common/static/common/js/components/views/paging_footer.js index 08f3257434..36d2c74f2a 100644 --- a/common/static/common/js/components/views/paging_footer.js +++ b/common/static/common/js/components/views/paging_footer.js @@ -23,7 +23,8 @@ var onFirstPage = !this.collection.hasPreviousPage(), onLastPage = !this.collection.hasNextPage(); if (this.hideWhenOnePage) { - if (this.collection.totalPages <= 1) { + if (_.isUndefined(this.collection.totalPages) + || this.collection.totalPages <= 1) { this.$el.addClass('hidden'); } else if (this.$el.hasClass('hidden')) { this.$el.removeClass('hidden'); diff --git a/common/static/common/js/components/views/paging_header.js b/common/static/common/js/components/views/paging_header.js index 3489b01b0f..3bed5147b1 100644 --- a/common/static/common/js/components/views/paging_header.js +++ b/common/static/common/js/components/views/paging_header.js @@ -16,9 +16,9 @@ render: function () { var message, - start = this.collection.start, + start = _.isUndefined(this.collection.start) ? 0 : this.collection.start, end = start + this.collection.length, - num_items = this.collection.totalCount, + num_items = _.isUndefined(this.collection.totalCount) ? 0 : this.collection.totalCount, context = {first_index: Math.min(start + 1, end), last_index: end, num_items: num_items}; if (end <= 1) { message = interpolate(gettext('Showing %(first_index)s out of %(num_items)s total'), context, true); diff --git a/common/static/common/js/spec/components/paginated_view_spec.js b/common/static/common/js/spec/components/paginated_view_spec.js new file mode 100644 index 0000000000..4e04ede8a6 --- /dev/null +++ b/common/static/common/js/spec/components/paginated_view_spec.js @@ -0,0 +1,184 @@ +define([ + 'backbone', + 'underscore', + 'common/js/spec_helpers/ajax_helpers', + 'common/js/components/views/paginated_view', + 'common/js/components/collections/paging_collection' +], function (Backbone, _, AjaxHelpers, PaginatedView, PagingCollection) { + 'use strict'; + describe('PaginatedView', function () { + var TestItemView = Backbone.View.extend({ + className: 'test-item', + tagName: 'div', + initialize: function () { + this.render(); + }, + render: function () { + this.$el.text(this.model.get('text')); + return this; + } + }), + TestPaginatedView = PaginatedView.extend({type: 'test', itemViewClass: TestItemView}), + testCollection, + testView, + initialItems, + nextPageButtonCss = '.next-page-link', + previousPageButtonCss = '.previous-page-link', + generateItems = function (numItems) { + return _.map(_.range(numItems), function (i) { + return { + text: 'item ' + i + }; + }); + }; + + beforeEach(function () { + setFixtures('
'); + initialItems = generateItems(5); + testCollection = new PagingCollection({ + count: 6, + num_pages: 2, + current_page: 1, + start: 0, + results: initialItems + }, {parse: true}); + testView = new TestPaginatedView({el: '.test-container', collection: testCollection}).render(); + }); + + /** + * Verify that the view's header reflects the page we're currently viewing. + * @param matchString the header we expect to see + */ + function expectHeader(matchString) { + expect(testView.$('.test-paging-header').text()).toMatch(matchString); + } + + /** + * Verify that the list view renders the expected items + * @param expectedItems an array of topic objects we expect to see + */ + function expectItems(expectedItems) { + var $items = testView.$('.test-item'); + _.each(expectedItems, function (item, index) { + var currentItem = $items.eq(index); + expect(currentItem.text()).toMatch(item.text); + }); + } + + /** + * Verify that the footer reflects the current pagination + * @param options a parameters hash containing: + * - currentPage: the one-indexed page we expect to be viewing + * - totalPages: the total number of pages to page through + * - isHidden: whether the footer is expected to be visible + */ + function expectFooter(options) { + var footerEl = testView.$('.test-paging-footer'); + expect(footerEl.text()) + .toMatch(new RegExp(options.currentPage + '\\s+out of\\s+\/\\s+' + testCollection.totalPages)); + expect(footerEl.hasClass('hidden')).toBe(options.isHidden); + } + + it('can render the first of many pages', function () { + expectHeader('Showing 1-5 out of 6 total'); + expectItems(initialItems); + expectFooter({currentPage: 1, totalPages: 2, isHidden: false}); + }); + + it('can render the only page', function () { + initialItems = generateItems(1); + testCollection.set( + { + "count": 1, + "num_pages": 1, + "current_page": 1, + "start": 0, + "results": initialItems + }, + {parse: true} + ); + expectHeader('Showing 1 out of 1 total'); + expectItems(initialItems); + expectFooter({currentPage: 1, totalPages: 1, isHidden: true}); + }); + + it('can change to the next page', function () { + var requests = AjaxHelpers.requests(this), + newItems = generateItems(1); + expectHeader('Showing 1-5 out of 6 total'); + expectItems(initialItems); + expectFooter({currentPage: 1, totalPages: 2, isHidden: false}); + expect(requests.length).toBe(0); + testView.$(nextPageButtonCss).click(); + expect(requests.length).toBe(1); + AjaxHelpers.respondWithJson(requests, { + "count": 6, + "num_pages": 2, + "current_page": 2, + "start": 5, + "results": newItems + }); + expectHeader('Showing 6-6 out of 6 total'); + expectItems(newItems); + expectFooter({currentPage: 2, totalPages: 2, isHidden: false}); + }); + + it('can change to the previous page', function () { + var requests = AjaxHelpers.requests(this), + previousPageItems; + initialItems = generateItems(1); + testCollection.set( + { + "count": 6, + "num_pages": 2, + "current_page": 2, + "start": 5, + "results": initialItems + }, + {parse: true} + ); + expectHeader('Showing 6-6 out of 6 total'); + expectItems(initialItems); + expectFooter({currentPage: 2, totalPages: 2, isHidden: false}); + testView.$(previousPageButtonCss).click(); + previousPageItems = generateItems(5); + AjaxHelpers.respondWithJson(requests, { + "count": 6, + "num_pages": 2, + "current_page": 1, + "start": 0, + "results": previousPageItems + }); + expectHeader('Showing 1-5 out of 6 total'); + expectItems(previousPageItems); + expectFooter({currentPage: 1, totalPages: 2, isHidden: false}); + }); + + it('sets focus for screen readers', function () { + var requests = AjaxHelpers.requests(this); + spyOn($.fn, 'focus'); + testView.$(nextPageButtonCss).click(); + AjaxHelpers.respondWithJson(requests, { + "count": 6, + "num_pages": 2, + "current_page": 2, + "start": 5, + "results": generateItems(1) + }); + expect(testView.$('.sr-is-focusable').focus).toHaveBeenCalled(); + }); + + it('does not change on server error', function () { + var requests = AjaxHelpers.requests(this), + expectInitialState = function () { + expectHeader('Showing 1-5 out of 6 total'); + expectItems(initialItems); + expectFooter({currentPage: 1, totalPages: 2, isHidden: false}); + }; + expectInitialState(); + testView.$(nextPageButtonCss).click(); + requests[0].respond(500); + expectInitialState(); + }); + }); +}); diff --git a/common/static/common/templates/components/paginated-view.underscore b/common/static/common/templates/components/paginated-view.underscore new file mode 100644 index 0000000000..09ea0a13b4 --- /dev/null +++ b/common/static/common/templates/components/paginated-view.underscore @@ -0,0 +1,4 @@ +
+
+
+ diff --git a/common/static/css/tinymce-studio-content-fonts.css b/common/static/css/tinymce-studio-content-fonts.css index e21ec0d35a..33f8f2acc4 100644 --- a/common/static/css/tinymce-studio-content-fonts.css +++ b/common/static/css/tinymce-studio-content-fonts.css @@ -2,89 +2,81 @@ /* No subsetting. */ @font-face { - font-family: 'Open Sans'; - src: url('../fonts/OpenSans/OpenSans-Light-webfont.eot'); - src: url('../fonts/OpenSans/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'), - url('../fonts/OpenSans/OpenSans-Light-webfont.woff') format('woff'), - url('../fonts/OpenSans/OpenSans-Light-webfont.ttf') format('truetype'), - url('../fonts/OpenSans/OpenSans-Light-webfont.svg#open_sanslight') format('svg'); - font-weight: 300; - font-style: normal; + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-Light-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-Light-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-Light-webfont.ttf') format('truetype'); + font-weight: 300; + font-style: normal; } @font-face { - font-family: 'Open Sans'; - src: url('../fonts/OpenSans/OpenSans-LightItalic-webfont.eot'); - src: url('../fonts/OpenSans/OpenSans-LightItalic-webfont.eot?#iefix') format('embedded-opentype'), - url('../fonts/OpenSans/OpenSans-LightItalic-webfont.woff') format('woff'), - url('../fonts/OpenSans/OpenSans-LightItalic-webfont.ttf') format('truetype'), - url('../fonts/OpenSans/OpenSans-LightItalic-webfont.svg#open_sanslight_italic') format('svg'); - font-weight: 300; - font-style: italic; + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-LightItalic-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-LightItalic-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-LightItalic-webfont.ttf') format('truetype'); + font-weight: 300; + font-style: italic; } @font-face { - font-family: 'Open Sans'; - src: url('../fonts/OpenSans/OpenSans-Regular-webfont.eot'); - src: url('../fonts/OpenSans/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'), - url('../fonts/OpenSans/OpenSans-Regular-webfont.woff') format('woff'), - url('../fonts/OpenSans/OpenSans-Regular-webfont.ttf') format('truetype'), - url('../fonts/OpenSans/OpenSans-Regular-webfont.svg#open_sansregular') format('svg'); - font-weight: 400; - font-style: normal; + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-Regular-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-Regular-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-Regular-webfont.ttf') format('truetype'); + font-weight: 400; + font-style: normal; } @font-face { - font-family: 'Open Sans'; - src: url('../fonts/OpenSans/OpenSans-Italic-webfont.eot'); - src: url('../fonts/OpenSans/OpenSans-Italic-webfont.eot?#iefix') format('embedded-opentype'), - url('../fonts/OpenSans/OpenSans-Italic-webfont.woff') format('woff'), - url('../fonts/OpenSans/OpenSans-Italic-webfont.ttf') format('truetype'), - url('../fonts/OpenSans/OpenSans-Italic-webfont.svg#open_sansitalic') format('svg'); - font-weight: 400; - font-style: italic; + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-Italic-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-Italic-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-Italic-webfont.ttf') format('truetype'); + font-weight: 400; + font-style: italic; } @font-face { - font-family: 'Open Sans'; - src: url('../fonts/OpenSans/OpenSans-Semibold-webfont.eot'); - src: url('../fonts/OpenSans/OpenSans-Semibold-webfont.eot?#iefix') format('embedded-opentype'), - url('../fonts/OpenSans/OpenSans-Semibold-webfont.woff') format('woff'), - url('../fonts/OpenSans/OpenSans-Semibold-webfont.ttf') format('truetype'), - url('../fonts/OpenSans/OpenSans-Semibold-webfont.svg#open_sanssemibold') format('svg'); - font-weight: 600; - font-style: normal; + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-Semibold-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-Semibold-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-Semibold-webfont.ttf') format('truetype'); + font-weight: 600; + font-style: normal; } @font-face { - font-family: 'Open Sans'; - src: url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.eot'); - src: url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.eot?#iefix') format('embedded-opentype'), - url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff') format('woff'), - url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.ttf') format('truetype'), - url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.svg#open_sanssemibold_italic') format('svg'); - font-weight: 600; - font-style: italic; + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-SemiboldItalic-webfont.ttf') format('truetype'); + font-weight: 600; + font-style: italic; } @font-face { - font-family: 'Open Sans'; - src: url('../fonts/OpenSans/OpenSans-Bold-webfont.eot'); - src: url('../fonts/OpenSans/OpenSans-Bold-webfont.eot?#iefix') format('embedded-opentype'), - url('../fonts/OpenSans/OpenSans-Bold-webfont.woff') format('woff'), - url('../fonts/OpenSans/OpenSans-Bold-webfont.ttf') format('truetype'), - url('../fonts/OpenSans/OpenSans-Bold-webfont.svg#open_sansbold') format('svg'); - font-weight: 700; - font-style: normal; + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-Bold-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-Bold-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-Bold-webfont.ttf') format('truetype'); + font-weight: 700; + font-style: normal; } @font-face { - font-family: 'Open Sans'; - src: url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.eot'); - src: url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.eot?#iefix') format('embedded-opentype'), - url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.woff') format('woff'), - url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.ttf') format('truetype'), - url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.svg#open_sansbold_italic') format('svg'); - font-weight: 700; - font-style: italic; + font-family: 'Open Sans'; + src: + url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.woff2') format('woff2'), + url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.woff') format('woff'), + url('../fonts/OpenSans/OpenSans-BoldItalic-webfont.ttf') format('truetype'); + font-weight: 700; + font-style: italic; } diff --git a/common/static/fonts/OpenSans/OpenSans-Bold-webfont.eot b/common/static/fonts/OpenSans/OpenSans-Bold-webfont.eot deleted file mode 100755 index 5b6e0e6f19..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-Bold-webfont.eot and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-Bold-webfont.svg b/common/static/fonts/OpenSans/OpenSans-Bold-webfont.svg deleted file mode 100755 index ff239cf156..0000000000 --- a/common/static/fonts/OpenSans/OpenSans-Bold-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common/static/fonts/OpenSans/OpenSans-Bold-webfont.woff2 b/common/static/fonts/OpenSans/OpenSans-Bold-webfont.woff2 old mode 100755 new mode 100644 index c80b2d2afb..f8eb6b3b1a Binary files a/common/static/fonts/OpenSans/OpenSans-Bold-webfont.woff2 and b/common/static/fonts/OpenSans/OpenSans-Bold-webfont.woff2 differ diff --git a/common/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.eot b/common/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.eot deleted file mode 100755 index b5e5e7cc3a..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.eot and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.svg b/common/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.svg deleted file mode 100755 index f3c1273878..0000000000 --- a/common/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.woff2 b/common/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.woff2 old mode 100755 new mode 100644 index 60d8de4f64..b0efa9aa5f Binary files a/common/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.woff2 and b/common/static/fonts/OpenSans/OpenSans-BoldItalic-webfont.woff2 differ diff --git a/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.eot b/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.eot deleted file mode 100755 index 73653a1b85..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.eot and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.svg b/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.svg deleted file mode 100755 index a9aed6ba3f..0000000000 --- a/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.svg +++ /dev/null @@ -1,146 +0,0 @@ - - - - -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 2011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.ttf b/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.ttf deleted file mode 100755 index d33fc355fb..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.ttf and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.woff b/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.woff deleted file mode 100755 index 223715a5fb..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.woff and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.woff2 b/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.woff2 deleted file mode 100755 index bbaa1d4ea6..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-ExtraBold-webfont.woff2 and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.eot b/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.eot deleted file mode 100755 index 68463e3881..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.eot and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.svg b/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.svg deleted file mode 100755 index 0d69082833..0000000000 --- a/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.svg +++ /dev/null @@ -1,146 +0,0 @@ - - - - -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 20102011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.ttf b/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.ttf deleted file mode 100755 index c60cff6e0d..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.ttf and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.woff b/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.woff deleted file mode 100755 index ddd0573dd2..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.woff and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.woff2 b/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.woff2 deleted file mode 100755 index eff8367bc9..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-ExtraBoldItalic-webfont.woff2 and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-Italic-webfont.eot b/common/static/fonts/OpenSans/OpenSans-Italic-webfont.eot deleted file mode 100755 index 54fd29dc25..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-Italic-webfont.eot and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-Italic-webfont.svg b/common/static/fonts/OpenSans/OpenSans-Italic-webfont.svg deleted file mode 100755 index ab4bb7e1bb..0000000000 --- a/common/static/fonts/OpenSans/OpenSans-Italic-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common/static/fonts/OpenSans/OpenSans-Italic-webfont.woff2 b/common/static/fonts/OpenSans/OpenSans-Italic-webfont.woff2 old mode 100755 new mode 100644 index 440b74c391..f465471d57 Binary files a/common/static/fonts/OpenSans/OpenSans-Italic-webfont.woff2 and b/common/static/fonts/OpenSans/OpenSans-Italic-webfont.woff2 differ diff --git a/common/static/fonts/OpenSans/OpenSans-Light-webfont.eot b/common/static/fonts/OpenSans/OpenSans-Light-webfont.eot deleted file mode 100755 index ea950e622f..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-Light-webfont.eot and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-Light-webfont.svg b/common/static/fonts/OpenSans/OpenSans-Light-webfont.svg deleted file mode 100755 index a36a5b7ee7..0000000000 --- a/common/static/fonts/OpenSans/OpenSans-Light-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common/static/fonts/OpenSans/OpenSans-Light-webfont.woff2 b/common/static/fonts/OpenSans/OpenSans-Light-webfont.woff2 old mode 100755 new mode 100644 index d0b43e0adf..1396b76299 Binary files a/common/static/fonts/OpenSans/OpenSans-Light-webfont.woff2 and b/common/static/fonts/OpenSans/OpenSans-Light-webfont.woff2 differ diff --git a/common/static/fonts/OpenSans/OpenSans-LightItalic-webfont.eot b/common/static/fonts/OpenSans/OpenSans-LightItalic-webfont.eot deleted file mode 100755 index fdacf6e4e1..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-LightItalic-webfont.eot and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-LightItalic-webfont.svg b/common/static/fonts/OpenSans/OpenSans-LightItalic-webfont.svg deleted file mode 100755 index 8cf6f52132..0000000000 --- a/common/static/fonts/OpenSans/OpenSans-LightItalic-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common/static/fonts/OpenSans/OpenSans-LightItalic-webfont.woff2 b/common/static/fonts/OpenSans/OpenSans-LightItalic-webfont.woff2 old mode 100755 new mode 100644 index 21a92a7e8d..ef68939910 Binary files a/common/static/fonts/OpenSans/OpenSans-LightItalic-webfont.woff2 and b/common/static/fonts/OpenSans/OpenSans-LightItalic-webfont.woff2 differ diff --git a/common/static/fonts/OpenSans/OpenSans-Regular-webfont.eot b/common/static/fonts/OpenSans/OpenSans-Regular-webfont.eot deleted file mode 100755 index 3953513ecd..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-Regular-webfont.eot and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-Regular-webfont.svg b/common/static/fonts/OpenSans/OpenSans-Regular-webfont.svg deleted file mode 100755 index a169e01ae8..0000000000 --- a/common/static/fonts/OpenSans/OpenSans-Regular-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common/static/fonts/OpenSans/OpenSans-Regular-webfont.woff2 b/common/static/fonts/OpenSans/OpenSans-Regular-webfont.woff2 old mode 100755 new mode 100644 index f778f9c845..e36e99b143 Binary files a/common/static/fonts/OpenSans/OpenSans-Regular-webfont.woff2 and b/common/static/fonts/OpenSans/OpenSans-Regular-webfont.woff2 differ diff --git a/common/static/fonts/OpenSans/OpenSans-Semibold-webfont.eot b/common/static/fonts/OpenSans/OpenSans-Semibold-webfont.eot deleted file mode 100755 index cfc3dd7b42..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-Semibold-webfont.eot and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-Semibold-webfont.svg b/common/static/fonts/OpenSans/OpenSans-Semibold-webfont.svg deleted file mode 100755 index 2704ab4431..0000000000 --- a/common/static/fonts/OpenSans/OpenSans-Semibold-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common/static/fonts/OpenSans/OpenSans-Semibold-webfont.woff2 b/common/static/fonts/OpenSans/OpenSans-Semibold-webfont.woff2 old mode 100755 new mode 100644 index 852f7106ce..21384febe4 Binary files a/common/static/fonts/OpenSans/OpenSans-Semibold-webfont.woff2 and b/common/static/fonts/OpenSans/OpenSans-Semibold-webfont.woff2 differ diff --git a/common/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.eot b/common/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.eot deleted file mode 100755 index 635848ce52..0000000000 Binary files a/common/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.eot and /dev/null differ diff --git a/common/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.svg b/common/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.svg deleted file mode 100755 index 66a1abd0e8..0000000000 --- a/common/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.svg +++ /dev/null @@ -1,1824 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff2 b/common/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff2 old mode 100755 new mode 100644 index b0c2a26b40..721dbc2c0b Binary files a/common/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff2 and b/common/static/fonts/OpenSans/OpenSans-SemiboldItalic-webfont.woff2 differ diff --git a/common/static/js/spec/main_requirejs.js b/common/static/js/spec/main_requirejs.js index 42a204e74a..ac83443fe6 100644 --- a/common/static/js/spec/main_requirejs.js +++ b/common/static/js/spec/main_requirejs.js @@ -156,6 +156,7 @@ define([ // Run the common tests that use RequireJS. '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' diff --git a/common/static/js/vendor/underscore.string.min.js b/common/static/js/vendor/underscore.string.min.js index 5248a6ecd2..659ddbed2a 100644 --- a/common/static/js/vendor/underscore.string.min.js +++ b/common/static/js/vendor/underscore.string.min.js @@ -1 +1 @@ -!function(e,t){"use strict";var n=t.prototype.trim,r=t.prototype.trimRight,i=t.prototype.trimLeft,s=function(e){return e*1||0},o=function(e,t){if(t<1)return"";var n="";while(t>0)t&1&&(n+=e),t>>=1,e+=e;return n},u=[].slice,a=function(e){return e==null?"\\s":e.source?e.source:"["+p.escapeRegExp(e)+"]"},f={lt:"<",gt:">",quot:'"',apos:"'",amp:"&"},l={};for(var c in f)l[f[c]]=c;var h=function(){function e(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}var n=o,r=function(){return r.cache.hasOwnProperty(arguments[0])||(r.cache[arguments[0]]=r.parse(arguments[0])),r.format.call(null,r.cache[arguments[0]],arguments)};return r.format=function(r,i){var s=1,o=r.length,u="",a,f=[],l,c,p,d,v,m;for(l=0;l=0?"+"+a:a,v=p[4]?p[4]=="0"?"0":p[4].charAt(1):" ",m=p[6]-t(a).length,d=p[6]?n(v,m):"",f.push(p[5]?a+d:d+a)}}return f.join("")},r.cache={},r.parse=function(e){var t=e,n=[],r=[],i=0;while(t){if((n=/^[^\x25]+/.exec(t))!==null)r.push(n[0]);else if((n=/^\x25{2}/.exec(t))!==null)r.push("%");else{if((n=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(t))===null)throw new Error("[_.sprintf] huh?");if(n[2]){i|=1;var s=[],o=n[2],u=[];if((u=/^([a-z_][a-z_\d]*)/i.exec(o))===null)throw new Error("[_.sprintf] huh?");s.push(u[1]);while((o=o.substring(u[0].length))!=="")if((u=/^\.([a-z_][a-z_\d]*)/i.exec(o))!==null)s.push(u[1]);else{if((u=/^\[(\d+)\]/.exec(o))===null)throw new Error("[_.sprintf] huh?");s.push(u[1])}n[2]=s}else i|=2;if(i===3)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");r.push(n)}t=t.substring(n[0].length)}return r},r}(),p={VERSION:"2.3.0",isBlank:function(e){return e==null&&(e=""),/^\s*$/.test(e)},stripTags:function(e){return e==null?"":t(e).replace(/<\/?[^>]+>/g,"")},capitalize:function(e){return e=e==null?"":t(e),e.charAt(0).toUpperCase()+e.slice(1)},chop:function(e,n){return e==null?[]:(e=t(e),n=~~n,n>0?e.match(new RegExp(".{1,"+n+"}","g")):[e])},clean:function(e){return p.strip(e).replace(/\s+/g," ")},count:function(e,n){return e==null||n==null?0:t(e).split(n).length-1},chars:function(e){return e==null?[]:t(e).split("")},swapCase:function(e){return e==null?"":t(e).replace(/\S/g,function(e){return e===e.toUpperCase()?e.toLowerCase():e.toUpperCase()})},escapeHTML:function(e){return e==null?"":t(e).replace(/[&<>"']/g,function(e){return"&"+l[e]+";"})},unescapeHTML:function(e){return e==null?"":t(e).replace(/\&([^;]+);/g,function(e,n){var r;return n in f?f[n]:(r=n.match(/^#x([\da-fA-F]+)$/))?t.fromCharCode(parseInt(r[1],16)):(r=n.match(/^#(\d+)$/))?t.fromCharCode(~~r[1]):e})},escapeRegExp:function(e){return e==null?"":t(e).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")},splice:function(e,t,n,r){var i=p.chars(e);return i.splice(~~t,~~n,r),i.join("")},insert:function(e,t,n){return p.splice(e,t,0,n)},include:function(e,n){return n===""?!0:e==null?!1:t(e).indexOf(n)!==-1},join:function(){var e=u.call(arguments),t=e.shift();return t==null&&(t=""),e.join(t)},lines:function(e){return e==null?[]:t(e).split("\n")},reverse:function(e){return p.chars(e).reverse().join("")},startsWith:function(e,n){return n===""?!0:e==null||n==null?!1:(e=t(e),n=t(n),e.length>=n.length&&e.slice(0,n.length)===n)},endsWith:function(e,n){return n===""?!0:e==null||n==null?!1:(e=t(e),n=t(n),e.length>=n.length&&e.slice(e.length-n.length)===n)},succ:function(e){return e==null?"":(e=t(e),e.slice(0,-1)+t.fromCharCode(e.charCodeAt(e.length-1)+1))},titleize:function(e){return e==null?"":t(e).replace(/(?:^|\s)\S/g,function(e){return e.toUpperCase()})},camelize:function(e){return p.trim(e).replace(/[-_\s]+(.)?/g,function(e,t){return t.toUpperCase()})},underscored:function(e){return p.trim(e).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(e){return p.trim(e).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},classify:function(e){return p.titleize(t(e).replace(/_/g," ")).replace(/\s/g,"")},humanize:function(e){return p.capitalize(p.underscored(e).replace(/_id$/,"").replace(/_/g," "))},trim:function(e,r){return e==null?"":!r&&n?n.call(e):(r=a(r),t(e).replace(new RegExp("^"+r+"+|"+r+"+$","g"),""))},ltrim:function(e,n){return e==null?"":!n&&i?i.call(e):(n=a(n),t(e).replace(new RegExp("^"+n+"+"),""))},rtrim:function(e,n){return e==null?"":!n&&r?r.call(e):(n=a(n),t(e).replace(new RegExp(n+"+$"),""))},truncate:function(e,n,r){return e==null?"":(e=t(e),r=r||"...",n=~~n,e.length>n?e.slice(0,n)+r:e)},prune:function(e,n,r){if(e==null)return"";e=t(e),n=~~n,r=r!=null?t(r):"...";if(e.length<=n)return e;var i=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},s=e.slice(0,n+1).replace(/.(?=\W*\w*$)/g,i);return s.slice(s.length-2).match(/\w\w/)?s=s.replace(/\s*\S+$/,""):s=p.rtrim(s.slice(0,s.length-1)),(s+r).length>e.length?e:e.slice(0,s.length)+r},words:function(e,t){return p.isBlank(e)?[]:p.trim(e,t).split(t||/\s+/)},pad:function(e,n,r,i){e=e==null?"":t(e),n=~~n;var s=0;r?r.length>1&&(r=r.charAt(0)):r=" ";switch(i){case"right":return s=n-e.length,e+o(r,s);case"both":return s=n-e.length,o(r,Math.ceil(s/2))+e+o(r,Math.floor(s/2));default:return s=n-e.length,o(r,s)+e}},lpad:function(e,t,n){return p.pad(e,t,n)},rpad:function(e,t,n){return p.pad(e,t,n,"right")},lrpad:function(e,t,n){return p.pad(e,t,n,"both")},sprintf:h,vsprintf:function(e,t){return t.unshift(e),h.apply(null,t)},toNumber:function(e,n){if(e==null||e=="")return 0;e=t(e);var r=s(s(e).toFixed(~~n));return r===0&&!e.match(/^0+$/)?Number.NaN:r},numberFormat:function(e,t,n,r){if(isNaN(e)||e==null)return"";e=e.toFixed(~~t),r=r||",";var i=e.split("."),s=i[0],o=i[1]?(n||".")+i[1]:"";return s.replace(/(\d)(?=(?:\d{3})+$)/g,"$1"+r)+o},strRight:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.indexOf(n):-1;return~r?e.slice(r+n.length,e.length):e},strRightBack:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.lastIndexOf(n):-1;return~r?e.slice(r+n.length,e.length):e},strLeft:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.indexOf(n):-1;return~r?e.slice(0,r):e},strLeftBack:function(e,t){if(e==null)return"";e+="",t=t!=null?""+t:t;var n=e.lastIndexOf(t);return~n?e.slice(0,n):e},toSentence:function(e,t,n,r){t=t||", ",n=n||" and ";var i=e.slice(),s=i.pop();return e.length>2&&r&&(n=p.rtrim(t)+n),i.length?i.join(t)+n+s:s},toSentenceSerial:function(){var e=u.call(arguments);return e[3]=!0,p.toSentence.apply(p,e)},slugify:function(e){if(e==null)return"";var n="ąàáäâãåæćęèéëêìíïîłńòóöôõøùúüûñçżź",r="aaaaaaaaceeeeeiiiilnoooooouuuunczz",i=new RegExp(a(n),"g");return e=t(e).toLowerCase().replace(i,function(e){var t=n.indexOf(e);return r.charAt(t)||"-"}),p.dasherize(e.replace(/[^\w\s-]/g,""))},surround:function(e,t){return[t,e,t].join("")},quote:function(e){return p.surround(e,'"')},exports:function(){var e={};for(var t in this){if(!this.hasOwnProperty(t)||t.match(/^(?:include|contains|reverse)$/))continue;e[t]=this[t]}return e},repeat:function(e,n,r){if(e==null)return"";n=~~n;if(r==null)return o(t(e),n);for(var i=[];n>0;i[--n]=e);return i.join(r)},levenshtein:function(e,n){if(e==null&&n==null)return 0;if(e==null)return t(n).length;if(n==null)return t(e).length;e=t(e),n=t(n);var r=[],i,s;for(var o=0;o<=n.length;o++)for(var u=0;u<=e.length;u++)o&&u?e.charAt(u-1)===n.charAt(o-1)?s=i:s=Math.min(r[u],r[u-1],i)+1:s=o+u,i=r[u],r[u]=s;return r.pop()}};p.strip=p.trim,p.lstrip=p.ltrim,p.rstrip=p.rtrim,p.center=p.lrpad,p.rjust=p.lpad,p.ljust=p.rpad,p.contains=p.include,p.q=p.quote,typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(module.exports=p),exports._s=p):typeof define=="function"&&define.amd?define("underscore.string",[],function(){return p}):(e._=e._||{},e._.string=e._.str=p)}(this,String); \ No newline at end of file +!function(e,t){"use strict";var n=t.prototype.trim,r=t.prototype.trimRight,i=t.prototype.trimLeft,s=function(e){return e*1||0},o=function(e,t){if(t<1)return"";var n="";while(t>0)t&1&&(n+=e),t>>=1,e+=e;return n},u=[].slice,a=function(e){return e==null?"\\s":e.source?e.source:"["+p.escapeRegExp(e)+"]"},f={lt:"<",gt:">",quot:'"',apos:"'",amp:"&"},l={};for(var c in f)l[f[c]]=c;var h=function(){function e(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}var n=o,r=function(){return r.cache.hasOwnProperty(arguments[0])||(r.cache[arguments[0]]=r.parse(arguments[0])),r.format.call(null,r.cache[arguments[0]],arguments)};return r.format=function(r,i){var s=1,o=r.length,u="",a,f=[],l,c,p,d,v,m;for(l=0;l=0?"+"+a:a,v=p[4]?p[4]=="0"?"0":p[4].charAt(1):" ",m=p[6]-t(a).length,d=p[6]?n(v,m):"",f.push(p[5]?a+d:d+a)}}return f.join("")},r.cache={},r.parse=function(e){var t=e,n=[],r=[],i=0;while(t){if((n=/^[^\x25]+/.exec(t))!==null)r.push(n[0]);else if((n=/^\x25{2}/.exec(t))!==null)r.push("%");else{if((n=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(t))===null)throw new Error("[_.sprintf] huh?");if(n[2]){i|=1;var s=[],o=n[2],u=[];if((u=/^([a-z_][a-z_\d]*)/i.exec(o))===null)throw new Error("[_.sprintf] huh?");s.push(u[1]);while((o=o.substring(u[0].length))!=="")if((u=/^\.([a-z_][a-z_\d]*)/i.exec(o))!==null)s.push(u[1]);else{if((u=/^\[(\d+)\]/.exec(o))===null)throw new Error("[_.sprintf] huh?");s.push(u[1])}n[2]=s}else i|=2;if(i===3)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");r.push(n)}t=t.substring(n[0].length)}return r},r}(),p={VERSION:"2.3.0",isBlank:function(e){return e==null&&(e=""),/^\s*$/.test(e)},stripTags:function(e){return e==null?"":t(e).replace(/<\/?[^>]+>/g,"")},capitalize:function(e){return e=e==null?"":t(e),e.charAt(0).toUpperCase()+e.slice(1)},chop:function(e,n){return e==null?[]:(e=t(e),n=~~n,n>0?e.match(new RegExp(".{1,"+n+"}","g")):[e])},clean:function(e){return p.strip(e).replace(/\s+/g," ")},count:function(e,n){return e==null||n==null?0:t(e).split(n).length-1},chars:function(e){return e==null?[]:t(e).split("")},swapCase:function(e){return e==null?"":t(e).replace(/\S/g,function(e){return e===e.toUpperCase()?e.toLowerCase():e.toUpperCase()})},escapeHTML:function(e){return e==null?"":t(e).replace(/[&<>"']/g,function(e){return"&"+l[e]+";"})},unescapeHTML:function(e){return e==null?"":t(e).replace(/\&([^;]+);/g,function(e,n){var r;return n in f?f[n]:(r=n.match(/^#x([\da-fA-F]+)$/))?t.fromCharCode(parseInt(r[1],16)):(r=n.match(/^#(\d+)$/))?t.fromCharCode(~~r[1]):e})},escapeRegExp:function(e){return e==null?"":t(e).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")},splice:function(e,t,n,r){var i=p.chars(e);return i.splice(~~t,~~n,r),i.join("")},insert:function(e,t,n){return p.splice(e,t,0,n)},include:function(e,n){return n===""?!0:e==null?!1:t(e).indexOf(n)!==-1},join:function(){var e=u.call(arguments),t=e.shift();return t==null&&(t=""),e.join(t)},lines:function(e){return e==null?[]:t(e).split("\n")},reverse:function(e){return p.chars(e).reverse().join("")},startsWith:function(e,n){return n===""?!0:e==null||n==null?!1:(e=t(e),n=t(n),e.length>=n.length&&e.slice(0,n.length)===n)},endsWith:function(e,n){return n===""?!0:e==null||n==null?!1:(e=t(e),n=t(n),e.length>=n.length&&e.slice(e.length-n.length)===n)},succ:function(e){return e==null?"":(e=t(e),e.slice(0,-1)+t.fromCharCode(e.charCodeAt(e.length-1)+1))},titleize:function(e){return e==null?"":t(e).replace(/(?:^|\s)\S/g,function(e){return e.toUpperCase()})},camelize:function(e){return p.trim(e).replace(/[-_\s]+(.)?/g,function(e,t){return t.toUpperCase()})},underscored:function(e){return p.trim(e).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(e){return p.trim(e).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},classify:function(e){return p.titleize(t(e).replace(/_/g," ")).replace(/\s/g,"")},humanize:function(e){return p.capitalize(p.underscored(e).replace(/_id$/,"").replace(/_/g," "))},trim:function(e,r){return e==null?"":!r&&n?n.call(e):(r=a(r),t(e).replace(new RegExp("^"+r+"+|"+r+"+$","g"),""))},ltrim:function(e,n){return e==null?"":!n&&i?i.call(e):(n=a(n),t(e).replace(new RegExp("^"+n+"+"),""))},rtrim:function(e,n){return e==null?"":!n&&r?r.call(e):(n=a(n),t(e).replace(new RegExp(n+"+$"),""))},truncate:function(e,n,r){return e==null?"":(e=t(e),r=r||"...",n=~~n,e.length>n?e.slice(0,n)+r:e)},prune:function(e,n,r){if(e==null)return"";e=t(e),n=~~n,r=r!=null?t(r):"...";if(e.length<=n)return e;var i=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},s=e.slice(0,n+1).replace(/.(?=\W*\w*$)/g,i);return s.slice(s.length-2).match(/\w\w/)?s=s.replace(/\s*\S+$/,""):s=p.rtrim(s.slice(0,s.length-1)),(s+r).length>e.length?e:e.slice(0,s.length)+r},words:function(e,t){return p.isBlank(e)?[]:p.trim(e,t).split(t||/\s+/)},pad:function(e,n,r,i){e=e==null?"":t(e),n=~~n;var s=0;r?r.length>1&&(r=r.charAt(0)):r=" ";switch(i){case"right":return s=n-e.length,e+o(r,s);case"both":return s=n-e.length,o(r,Math.ceil(s/2))+e+o(r,Math.floor(s/2));default:return s=n-e.length,o(r,s)+e}},lpad:function(e,t,n){return p.pad(e,t,n)},rpad:function(e,t,n){return p.pad(e,t,n,"right")},lrpad:function(e,t,n){return p.pad(e,t,n,"both")},sprintf:h,vsprintf:function(e,t){return t.unshift(e),h.apply(null,t)},toNumber:function(e,n){if(e==null||e=="")return 0;e=t(e);var r=s(s(e).toFixed(~~n));return r===0&&!e.match(/^0+$/)?Number.NaN:r},numberFormat:function(e,t,n,r){if(isNaN(e)||e==null)return"";e=e.toFixed(~~t),r=r||",";var i=e.split("."),s=i[0],o=i[1]?(n||".")+i[1]:"";return s.replace(/(\d)(?=(?:\d{3})+$)/g,"$1"+r)+o},strRight:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.indexOf(n):-1;return~r?e.slice(r+n.length,e.length):e},strRightBack:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.lastIndexOf(n):-1;return~r?e.slice(r+n.length,e.length):e},strLeft:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.indexOf(n):-1;return~r?e.slice(0,r):e},strLeftBack:function(e,t){if(e==null)return"";e+="",t=t!=null?""+t:t;var n=e.lastIndexOf(t);return~n?e.slice(0,n):e},toSentence:function(e,t,n,r){t=t||", ",n=n||" and ";var i=e.slice(),s=i.pop();return e.length>2&&r&&(n=p.rtrim(t)+n),i.length?i.join(t)+n+s:s},toSentenceSerial:function(){var e=u.call(arguments);return e[3]=!0,p.toSentence.apply(p,e)},slugify:function(e){if(e==null)return"";var n="ąàáäâãåæćęèéëêìíïîłńòóöôõøùúüûñçżź",r="aaaaaaaaceeeeeiiiilnoooooouuuunczz",i=new RegExp(a(n),"g");return e=t(e).toLowerCase().replace(i,function(e){var t=n.indexOf(e);return r.charAt(t)||"-"}),p.dasherize(e.replace(/[^\w\s-]/g,""))},surround:function(e,t){return[t,e,t].join("")},quote:function(e){return p.surround(e,'"')},exports:function(){var e={};for(var t in this){if(!this.hasOwnProperty(t)||t.match(/^(?:include|contains|reverse)$/))continue;e[t]=this[t]}return e},repeat:function(e,n,r){if(e==null)return"";n=~~n;if(r==null)return o(t(e),n);for(var i=[];n>0;i[--n]=e);return i.join(r)},levenshtein:function(e,n){if(e==null&&n==null)return 0;if(e==null)return t(n).length;if(n==null)return t(e).length;e=t(e),n=t(n);var r=[],i,s;for(var o=0;o<=n.length;o++)for(var u=0;u<=e.length;u++)o&&u?e.charAt(u-1)===n.charAt(o-1)?s=i:s=Math.min(r[u],r[u-1],i)+1:s=o+u,i=r[u],r[u]=s;return r.pop()}};p.strip=p.trim,p.lstrip=p.ltrim,p.rstrip=p.rtrim,p.center=p.lrpad,p.rjust=p.lpad,p.ljust=p.rpad,p.contains=p.include,p.q=p.quote,typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(module.exports=p),exports._s=p):typeof define==="function"&&define.amd?define("underscore.string",[],function(){return p}):(e._=e._||{},e._.string=e._.str=p)}(this,String); \ No newline at end of file diff --git a/common/templates/edxnotes_wrapper.html b/common/templates/edxnotes_wrapper.html index d549bb68a4..6742a7c152 100644 --- a/common/templates/edxnotes_wrapper.html +++ b/common/templates/edxnotes_wrapper.html @@ -3,6 +3,7 @@ import json from django.utils.translation import ugettext as _ from student.models import anonymous_id_for_user %> +<%namespace name='static' file='/static_content.html'/> <% if user: params.update({'user': anonymous_id_for_user(user, None)}) @@ -10,11 +11,7 @@ from student.models import anonymous_id_for_user
${content}
- +<%static:require_module module_name="js/edxnotes/views/notes_visibility_factory" class_name="NotesVisibilityFactory"> + var element = document.getElementById('edx-notes-wrapper-${uid}'); + NotesVisibilityFactory.VisibilityDecorator.factory(element, ${json.dumps(params)}, ${edxnotes_visibility}); + diff --git a/common/test/acceptance/pages/lms/certificate_page.py b/common/test/acceptance/pages/lms/certificate_page.py index e2a161caa8..6b6781bd0c 100644 --- a/common/test/acceptance/pages/lms/certificate_page.py +++ b/common/test/acceptance/pages/lms/certificate_page.py @@ -49,7 +49,7 @@ class CertificatePage(PageObject): """ returns add to LinkedIn profile button """ - return self.q(css='a.action-linkedin-profile') + return self.q(css='button.action-linkedin-profile') @property def add_to_facebook_profile_button(self): diff --git a/common/test/acceptance/pages/lms/dashboard.py b/common/test/acceptance/pages/lms/dashboard.py index d52f3fe148..cba42d2154 100644 --- a/common/test/acceptance/pages/lms/dashboard.py +++ b/common/test/acceptance/pages/lms/dashboard.py @@ -4,7 +4,6 @@ Student dashboard page. """ from bok_choy.page_object import PageObject -from bok_choy.promise import EmptyPromise from . import BASE_URL @@ -160,14 +159,14 @@ class DashboardPage(PageObject): """ return self.q(css='.dropdown-menu li a').text - def click_account_settings_link(self): - """ - Click on `Account Settings` link. - """ - self.q(css='.dropdown-menu li a').first.click() - def click_my_profile_link(self): """ - Click on `My Profile` link. + Click on `Profile` link. """ self.q(css='.dropdown-menu li a').nth(1).click() + + def click_account_settings_link(self): + """ + Click on `Account` link. + """ + self.q(css='.dropdown-menu li a').nth(2).click() diff --git a/common/test/acceptance/pages/lms/edxnotes.py b/common/test/acceptance/pages/lms/edxnotes.py index 552e9a06ed..80b482f2d2 100644 --- a/common/test/acceptance/pages/lms/edxnotes.py +++ b/common/test/acceptance/pages/lms/edxnotes.py @@ -174,7 +174,7 @@ class EdxNotesPageView(PageObject): self.q(css=self.TAB_SELECTOR).first.click() try: return self.wait_for_page() - except (BrokenPromise): + except BrokenPromise: raise PageLoadError("Timed out waiting to load page '{!r}'".format(self)) def is_browser_on_page(self): diff --git a/common/test/acceptance/pages/lms/find_courses.py b/common/test/acceptance/pages/lms/find_courses.py index 0a008588b1..564891b1f3 100644 --- a/common/test/acceptance/pages/lms/find_courses.py +++ b/common/test/acceptance/pages/lms/find_courses.py @@ -3,7 +3,6 @@ Find courses page (main page of the LMS). """ from bok_choy.page_object import PageObject -from bok_choy.promise import BrokenPromise from . import BASE_URL diff --git a/common/test/acceptance/pages/lms/login_and_register.py b/common/test/acceptance/pages/lms/login_and_register.py index 9cbd6af99f..bc9efe67ec 100644 --- a/common/test/acceptance/pages/lms/login_and_register.py +++ b/common/test/acceptance/pages/lms/login_and_register.py @@ -197,7 +197,7 @@ class CombinedLoginAndRegisterPage(PageObject): self.q(css="#register-password").fill(password) if country: self.q(css="#register-country option[value='{country}']".format(country=country)).click() - if (terms_of_service): + if terms_of_service: self.q(css="#register-honor_code").click() # Submit it diff --git a/common/test/acceptance/pages/lms/pay_and_verify.py b/common/test/acceptance/pages/lms/pay_and_verify.py index 0b27a0d69d..3897610b88 100644 --- a/common/test/acceptance/pages/lms/pay_and_verify.py +++ b/common/test/acceptance/pages/lms/pay_and_verify.py @@ -1,10 +1,9 @@ """Payment and verification pages""" import re -from urllib import urlencode -from bok_choy.page_object import PageObject, unguarded -from bok_choy.promise import Promise, EmptyPromise +from bok_choy.page_object import PageObject +from bok_choy.promise import Promise from . import BASE_URL from .dashboard import DashboardPage diff --git a/common/test/acceptance/pages/lms/teams.py b/common/test/acceptance/pages/lms/teams.py index de6b81c215..ce224ebb9c 100644 --- a/common/test/acceptance/pages/lms/teams.py +++ b/common/test/acceptance/pages/lms/teams.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ -Teams page. +Teams pages. """ from .course_page import CoursePage @@ -9,6 +9,8 @@ from ..common.paging import PaginatedUIMixin TOPIC_CARD_CSS = 'div.wrapper-card-core' BROWSE_BUTTON_CSS = 'a.nav-item[data-index="1"]' +TEAMS_LINK_CSS = '.action-view' +TEAMS_HEADER_CSS = '.teams-header' class TeamsPage(CoursePage): @@ -53,3 +55,50 @@ class BrowseTopicsPage(CoursePage, PaginatedUIMixin): def topic_cards(self): """Return a list of the topic cards present on the page.""" return self.q(css=TOPIC_CARD_CSS).results + + def browse_teams_for_topic(self, topic_name): + """ + Show the teams list for `topic_name`. + """ + self.q(css=TEAMS_LINK_CSS).filter( + text='View Teams in the {topic_name} Topic'.format(topic_name=topic_name) + )[0].click() + self.wait_for_ajax() + + +class BrowseTeamsPage(CoursePage, PaginatedUIMixin): + """ + 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. + """ + super(BrowseTeamsPage, 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.""" + 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): + """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): + """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') diff --git a/common/test/acceptance/pages/lms/track_selection.py b/common/test/acceptance/pages/lms/track_selection.py index 86ce7488f1..3b701d69e8 100644 --- a/common/test/acceptance/pages/lms/track_selection.py +++ b/common/test/acceptance/pages/lms/track_selection.py @@ -1,9 +1,5 @@ """Track selection page""" - -from urllib import urlencode - -from bok_choy.page_object import PageObject, unguarded -from bok_choy.promise import Promise, EmptyPromise +from bok_choy.page_object import PageObject from . import BASE_URL from .dashboard import DashboardPage from .pay_and_verify import PaymentAndVerificationFlow diff --git a/common/test/acceptance/pages/studio/overview.py b/common/test/acceptance/pages/studio/overview.py index 842bd0d0dc..f648007fe0 100644 --- a/common/test/acceptance/pages/studio/overview.py +++ b/common/test/acceptance/pages/studio/overview.py @@ -8,7 +8,6 @@ from bok_choy.promise import EmptyPromise from selenium.webdriver.support.ui import Select from selenium.webdriver.common.keys import Keys -from selenium.webdriver.common.action_chains import ActionChains from .course_page import CoursePage from .container import ContainerPage @@ -405,7 +404,7 @@ class CourseOutlineSection(CourseOutlineContainer, CourseOutlineChild): self.add_child() -class ExpandCollapseLinkState: +class ExpandCollapseLinkState(object): """ Represents the three states that the expand/collapse link can be in """ diff --git a/common/test/acceptance/pages/studio/settings_certificates.py b/common/test/acceptance/pages/studio/settings_certificates.py index 6d521efbaa..5916de4359 100644 --- a/common/test/acceptance/pages/studio/settings_certificates.py +++ b/common/test/acceptance/pages/studio/settings_certificates.py @@ -79,8 +79,18 @@ class CertificatesPage(CoursePage): We can't use confirm_prompt because its wait_for_notification is flaky when asynchronous operation completed very quickly. """ - self.wait_for_element_visibility('.prompt', 'Prompt is visible') - self.wait_for_element_visibility('.prompt .action-primary', 'Confirmation button is visible') + EmptyPromise( + lambda: self.q(css='.prompt').present, + 'Confirmation prompt is displayed' + ).fulfill() + EmptyPromise( + lambda: self.q(css='.prompt .action-primary').present, + 'Primary button is displayed' + ).fulfill() + EmptyPromise( + lambda: self.q(css='.prompt .action-primary').visible, + 'Primary button is visible' + ).fulfill() def wait_for_first_certificate_button(self): """ @@ -108,17 +118,23 @@ class CertificatesPage(CoursePage): """ Clicks the 'Create your first certificate' button, which is only displayed at zero state """ + self.wait_for_first_certificate_button() self.q(css=self.certficate_css + " .new-button").first.click() def click_add_certificate_button(self): """ Clicks the 'Add new certificate' button, which is displayed when certificates already exist """ + self.wait_for_add_certificate_button() self.q(css=self.certficate_css + " .action-add").first.click() - ################ - # Workflows - ################ + def click_confirmation_prompt_primary_button(self): + """ + Clicks the main action presented by the prompt (such as 'Delete') + """ + self.wait_for_confirmation_prompt() + self.q(css='a.button.action-primary').first.click() + self.wait_for_ajax() class Certificate(object): @@ -240,13 +256,19 @@ class Certificate(object): """ Returns whether or not the certificate delete icon is present. """ - return self.find_css('.actions .delete').present + EmptyPromise( + lambda: self.find_css('.actions .delete').present, + 'Certificate delete button is displayed' + ).fulfill() def wait_for_hide_details_toggle(self): """ Certificate details are expanded. """ - return self.find_css('a.detail-toggle.hide-details').present + EmptyPromise( + lambda: self.find_css('a.detail-toggle.hide-details').present, + 'Certificate details are expanded' + ).fulfill() ################ # Click Actions @@ -290,20 +312,12 @@ class Certificate(object): """ self.find_css('a.detail-toggle').first.click() - ################ - # Workflows - ################ - - def delete_certificate(self): + def click_delete_certificate_button(self): """ - Delete the certificate + Remove the first (possibly the only) certificate from the set """ self.wait_for_certificate_delete_button() - self.find_css('.actions .delete').first.click() - self.page.wait_for_confirmation_prompt() - self.page.q(css='a.button.action-primary').first.click() - self.page.q(css='a.button.action-primary').first.click() self.page.wait_for_ajax() diff --git a/common/test/acceptance/performance/test_lms_performance.py b/common/test/acceptance/performance/test_lms_performance.py index 1673eff593..dcde42220c 100644 --- a/common/test/acceptance/performance/test_lms_performance.py +++ b/common/test/acceptance/performance/test_lms_performance.py @@ -1,7 +1,7 @@ """ Single page performance tests for LMS. """ -from bok_choy.web_app_test import WebAppTest, with_cache +from bok_choy.web_app_test import with_cache from ..pages.lms.auto_auth import AutoAuthPage from ..pages.lms.courseware import CoursewarePage from ..pages.lms.dashboard import DashboardPage diff --git a/common/test/acceptance/tests/helpers.py b/common/test/acceptance/tests/helpers.py index 1b8b597520..b521ddfca0 100644 --- a/common/test/acceptance/tests/helpers.py +++ b/common/test/acceptance/tests/helpers.py @@ -67,8 +67,7 @@ def is_youtube_available(): youtube_api_urls = { 'main': 'https://www.youtube.com/', - 'player': 'http://www.youtube.com/iframe_api', - 'metadata': 'http://gdata.youtube.com/feeds/api/videos/', + 'player': 'https://www.youtube.com/iframe_api', # For transcripts, you need to check an actual video, so we will # just specify our default video and see if that one is available. 'transcript': 'http://video.google.com/timedtext?lang=en&v=3_yD_cEKoCk', diff --git a/common/test/acceptance/tests/lms/test_account_settings.py b/common/test/acceptance/tests/lms/test_account_settings.py index efdcd1c00b..9e8c504509 100644 --- a/common/test/acceptance/tests/lms/test_account_settings.py +++ b/common/test/acceptance/tests/lms/test_account_settings.py @@ -85,19 +85,19 @@ class DashboardMenuTest(AccountSettingsTestMixin, WebAppTest): """ def test_link_on_dashboard_works(self): """ - Scenario: Verify that the "Account Settings" link works from the dashboard. + Scenario: Verify that the "Account" link works from the dashboard. Given that I am a registered user And I visit my dashboard - And I click on "Account Settings" in the top drop down + And I click on "Account" in the top drop down Then I should see my account settings page """ self.log_in_as_unique_user() dashboard_page = DashboardPage(self.browser) dashboard_page.visit() dashboard_page.click_username_dropdown() - self.assertIn('Account Settings', dashboard_page.username_dropdown_link_text) + self.assertIn('Account', dashboard_page.username_dropdown_link_text) dashboard_page.click_account_settings_link() diff --git a/common/test/acceptance/tests/lms/test_learner_profile.py b/common/test/acceptance/tests/lms/test_learner_profile.py index 9e2af85b9e..9f412495a2 100644 --- a/common/test/acceptance/tests/lms/test_learner_profile.py +++ b/common/test/acceptance/tests/lms/test_learner_profile.py @@ -237,15 +237,15 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest): Given that I am a registered user. When I go to Dashboard page. And I click on username dropdown. - Then I see My Profile link in the dropdown menu. - When I click on My Profile link. - Then I will be navigated to My Profile page. + Then I see Profile link in the dropdown menu. + When I click on Profile link. + Then I will be navigated to Profile page. """ username, user_id = self.log_in_as_unique_user() dashboard_page = DashboardPage(self.browser) dashboard_page.visit() dashboard_page.click_username_dropdown() - self.assertTrue('My Profile' in dashboard_page.username_dropdown_link_text) + self.assertTrue('Profile' in dashboard_page.username_dropdown_link_text) dashboard_page.click_my_profile_link() my_profile_page = LearnerProfilePage(self.browser, username) my_profile_page.wait_for_page() @@ -255,7 +255,7 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest): Scenario: Verify that desired fields are shown when looking at her own private profile. Given that I am a registered user. - And I visit My Profile page. + And I visit my Profile page. And I set the profile visibility to private. And I reload the page. Then I should see the profile visibility selector dropdown. @@ -271,7 +271,7 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest): Scenario: Verify that desired fields are shown when looking at her own public profile. Given that I am a registered user. - And I visit My Profile page. + And I visit my Profile page. And I set the profile visibility to public. And I reload the page. Then I should see the profile visibility selector dropdown. @@ -316,7 +316,7 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest): Test behaviour of `Country` field. Given that I am a registered user. - And I visit My Profile page. + And I visit my Profile page. And I set the profile visibility to public and set default values for public fields. Then I set country value to `Pakistan`. Then displayed country should be `Pakistan` and country field mode should be `display` @@ -340,7 +340,7 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest): Test behaviour of `Language` field. Given that I am a registered user. - And I visit My Profile page. + And I visit my Profile page. And I set the profile visibility to public and set default values for public fields. Then I set language value to `Urdu`. Then displayed language should be `Urdu` and language field mode should be `display` @@ -369,7 +369,7 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest): Test behaviour of `About Me` field. Given that I am a registered user. - And I visit My Profile page. + And I visit my Profile page. And I set the profile visibility to public and set default values for public fields. Then I set about me value to `Eat Sleep Code`. Then displayed about me should be `Eat Sleep Code` and about me field mode should be `display` diff --git a/common/test/acceptance/tests/lms/test_lms.py b/common/test/acceptance/tests/lms/test_lms.py index 4ab4c5ce79..9d0ae381c2 100644 --- a/common/test/acceptance/tests/lms/test_lms.py +++ b/common/test/acceptance/tests/lms/test_lms.py @@ -9,7 +9,6 @@ from unittest import skip from nose.plugins.attrib import attr from bok_choy.promise import EmptyPromise -from bok_choy.web_app_test import WebAppTest from ..helpers import ( UniqueCourseTest, EventsTestMixin, diff --git a/common/test/acceptance/tests/lms/test_lms_cohorted_courseware_search.py b/common/test/acceptance/tests/lms/test_lms_cohorted_courseware_search.py index 323d1bebf0..90cad93bff 100644 --- a/common/test/acceptance/tests/lms/test_lms_cohorted_courseware_search.py +++ b/common/test/acceptance/tests/lms/test_lms_cohorted_courseware_search.py @@ -4,6 +4,7 @@ Test courseware search import os import json +from ..helpers import remove_file from ...pages.common.logout import LogoutPage from ...pages.studio.overview import CourseOutlinePage from ...pages.lms.courseware_search import CoursewareSearchPage @@ -40,6 +41,7 @@ class CoursewareSearchCohortTest(ContainerBase): # create test file in which index for this test will live with open(self.TEST_INDEX_FILENAME, "w+") as index_file: json.dump({}, index_file) + self.addCleanup(remove_file, self.TEST_INDEX_FILENAME) super(CoursewareSearchCohortTest, self).setUp(is_staff=is_staff) self.staff_user = self.user @@ -79,10 +81,6 @@ class CoursewareSearchCohortTest(ContainerBase): self._studio_reindex() - def tearDown(self): - super(CoursewareSearchCohortTest, self).tearDown() - os.remove(self.TEST_INDEX_FILENAME) - def _auto_auth(self, username, email, staff): """ Logout and login with given credentials. diff --git a/common/test/acceptance/tests/lms/test_lms_course_discovery.py b/common/test/acceptance/tests/lms/test_lms_course_discovery.py index 084a15b4e5..8bfe044770 100644 --- a/common/test/acceptance/tests/lms/test_lms_course_discovery.py +++ b/common/test/acceptance/tests/lms/test_lms_course_discovery.py @@ -2,9 +2,7 @@ Test course discovery. """ import datetime -from flaky import flaky import json -import os from bok_choy.web_app_test import WebAppTest from ..helpers import remove_file diff --git a/common/test/acceptance/tests/lms/test_lms_courseware_search.py b/common/test/acceptance/tests/lms/test_lms_courseware_search.py index 30f4153d76..8b94b185f7 100644 --- a/common/test/acceptance/tests/lms/test_lms_courseware_search.py +++ b/common/test/acceptance/tests/lms/test_lms_courseware_search.py @@ -1,7 +1,6 @@ """ Test courseware search """ -import os import json from nose.plugins.attrib import attr diff --git a/common/test/acceptance/tests/lms/test_lms_edxnotes.py b/common/test/acceptance/tests/lms/test_lms_edxnotes.py index 3bc66aa3da..b51ebdfab0 100644 --- a/common/test/acceptance/tests/lms/test_lms_edxnotes.py +++ b/common/test/acceptance/tests/lms/test_lms_edxnotes.py @@ -1,4 +1,6 @@ -import os +""" +Test LMS Notes +""" from uuid import uuid4 from datetime import datetime from nose.plugins.attrib import attr diff --git a/common/test/acceptance/tests/lms/test_lms_split_test_courseware_search.py b/common/test/acceptance/tests/lms/test_lms_split_test_courseware_search.py index 57bfac76e5..094152d16a 100644 --- a/common/test/acceptance/tests/lms/test_lms_split_test_courseware_search.py +++ b/common/test/acceptance/tests/lms/test_lms_split_test_courseware_search.py @@ -4,6 +4,7 @@ Test courseware search import os import json +from ..helpers import remove_file from ...pages.common.logout import LogoutPage from ...pages.studio.overview import CourseOutlinePage from ...pages.lms.courseware_search import CoursewareSearchPage @@ -37,6 +38,7 @@ class SplitTestCoursewareSearchTest(ContainerBase): # create test file in which index for this test will live with open(self.TEST_INDEX_FILENAME, "w+") as index_file: json.dump({}, index_file) + self.addCleanup(remove_file, self.TEST_INDEX_FILENAME) super(SplitTestCoursewareSearchTest, self).setUp(is_staff=is_staff) self.staff_user = self.user @@ -53,10 +55,6 @@ class SplitTestCoursewareSearchTest(ContainerBase): self._add_and_configure_split_test() self._studio_reindex() - def tearDown(self): - super(SplitTestCoursewareSearchTest, self).tearDown() - os.remove(self.TEST_INDEX_FILENAME) - def _auto_auth(self, username, email, staff): """ Logout and login with given credentials. diff --git a/common/test/acceptance/tests/lms/test_lms_user_preview.py b/common/test/acceptance/tests/lms/test_lms_user_preview.py index ff23534ee3..292bbf8dcf 100644 --- a/common/test/acceptance/tests/lms/test_lms_user_preview.py +++ b/common/test/acceptance/tests/lms/test_lms_user_preview.py @@ -7,7 +7,6 @@ from ..helpers import UniqueCourseTest, create_user_partition_json from ...pages.studio.auto_auth import AutoAuthPage from ...pages.lms.courseware import CoursewarePage from ...pages.lms.staff_view import StaffPage -from ...pages.lms.course_nav import CourseNavPage from ...fixtures.course import CourseFixture, XBlockFixtureDesc from xmodule.partitions.partitions import Group from textwrap import dedent diff --git a/common/test/acceptance/tests/lms/test_teams.py b/common/test/acceptance/tests/lms/test_teams.py index a212dd30b4..ae1f9917cf 100644 --- a/common/test/acceptance/tests/lms/test_teams.py +++ b/common/test/acceptance/tests/lms/test_teams.py @@ -1,23 +1,23 @@ """ Acceptance tests for the teams feature. """ -from ..helpers import UniqueCourseTest -from ...pages.lms.teams import TeamsPage, BrowseTopicsPage +import json + from nose.plugins.attrib import attr + +from ..helpers import UniqueCourseTest +from ...pages.lms.teams import TeamsPage, BrowseTopicsPage, BrowseTeamsPage +from ...fixtures import LMS_BASE_URL from ...fixtures.course import CourseFixture from ...pages.lms.tab_nav import TabNavPage from ...pages.lms.auto_auth import AutoAuthPage from ...pages.lms.course_info import CourseInfoPage -@attr('shard_5') -class TeamsTabTest(UniqueCourseTest): - """ - Tests verifying when the Teams tab is present. - """ - +class TeamsTabBase(UniqueCourseTest): + """Base class for Teams Tab tests""" def setUp(self): - super(TeamsTabTest, self).setUp() + super(TeamsTabBase, self).setUp() self.tab_nav = TabNavPage(self.browser) self.course_info_page = CourseInfoPage(self.browser, self.course_id) self.teams_page = TeamsPage(self.browser, self.course_id) @@ -39,7 +39,8 @@ class TeamsTabTest(UniqueCourseTest): self.course_fixture.install() enroll_course_id = self.course_id if enroll_in_course else None - AutoAuthPage(self.browser, course_id=enroll_course_id, staff=global_staff).visit() + #pylint: disable=attribute-defined-outside-init + self.user_info = AutoAuthPage(self.browser, course_id=enroll_course_id, staff=global_staff).visit().user_info self.course_info_page.visit() def verify_teams_present(self, present): @@ -54,6 +55,12 @@ class TeamsTabTest(UniqueCourseTest): else: self.assertNotIn("Teams", self.tab_nav.tab_names) + +@attr('shard_5') +class TeamsTabTest(TeamsTabBase): + """ + Tests verifying when the Teams tab is present. + """ def test_teams_not_enabled(self): """ Scenario: teams tab should not be present if no team configuration is set @@ -118,7 +125,7 @@ class TeamsTabTest(UniqueCourseTest): @attr('shard_5') -class BrowseTopicsTest(TeamsTabTest): +class BrowseTopicsTest(TeamsTabBase): """ Tests for the Browse tab of the Teams page. """ @@ -228,3 +235,223 @@ class BrowseTopicsTest(TeamsTabTest): self.assertLess(len(truncated_description), len(initial_description)) self.assertTrue(truncated_description.endswith('...')) self.assertIn(truncated_description.split('...')[0], initial_description) + + def test_go_to_teams_list(self): + """ + Scenario: Clicking on a Topic Card should take you to the + teams list for that Topic. + Given I am enrolled in a course with a team configuration and a topic + When I visit the Teams page + And I browse topics + And I click on the arrow link to view teams for the first topic + Then I should be on the browse teams page + """ + topic = {u"name": u"Example Topic", u"id": u"example_topic", u"description": "Description"} + self.set_team_configuration( + {u"max_team_size": 1, u"topics": [topic]} + ) + self.topics_page.visit() + 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') + + +@attr('shard_5') +class BrowseTeamsWithinTopicTest(TeamsTabBase): + """ + Tests for browsing Teams within a Topic on the Teams page. + """ + TEAMS_PAGE_SIZE = 10 + + 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.browse_teams_page = BrowseTeamsPage(self.browser, self.course_id, self.topic) + + def create_teams(self, num_teams): + """Create `num_teams` teams belonging to `self.topic`.""" + teams = [] + for i in xrange(num_teams): + team = { + 'course_id': self.course_id, + 'topic_id': self.topic['id'], + 'name': 'Team {}'.format(i), + 'description': 'Description {}'.format(i) + } + response = self.course_fixture.session.post( + LMS_BASE_URL + '/api/team/v0/teams/', + data=json.dumps(team), + headers=self.course_fixture.headers + ) + teams.append(json.loads(response.text)) + return teams + + def create_membership(self, username, team_id): + """Assign `username` to `team_id`.""" + response = self.course_fixture.session.post( + LMS_BASE_URL + '/api/team/v0/team_membership/', + data=json.dumps({'username': username, 'team_id': team_id}), + headers=self.course_fixture.headers + ) + return json.loads(response.text) + + 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']) + + def verify_teams(self, expected_teams): + """Verify that the list of team cards on the current page match the expected teams in order.""" + + def assert_team_equal(expected_team, team_card_name, team_card_description): + """ + Helper to assert that a single team card has the expected name and + description. + """ + self.assertEqual(expected_team['name'], team_card_name) + self.assertEqual(expected_team['description'], team_card_description) + + team_cards = self.browse_teams_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 + ] + map(assert_team_equal, expected_teams, team_card_names, team_card_descriptions) + + def verify_on_page(self, 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 + 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 + pagination header. + 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) + self.verify_teams(alphabetized_teams[(page_num - 1) * self.TEAMS_PAGE_SIZE:page_num * self.TEAMS_PAGE_SIZE]) + self.assertEqual( + self.browse_teams_page.pagination_controls_visible(), + footer_visible, + msg='Expected paging footer to be ' + 'visible' if footer_visible else 'invisible' + ) + + def test_no_teams(self): + """ + Scenario: Visiting a topic with no teams should not display any teams. + Given I am enrolled in a course with a team configuration and a topic + When I visit the Teams page for that topic + Then I should see the correct page header + And I should see a pagination header showing no teams + And I should see no teams + And I should see a button to add a team + And I should not see a pagination footer + """ + 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.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(), + msg='Expected paging footer to be invisible' + ) + + def test_teams_one_page(self): + """ + Scenario: Visiting a topic with fewer teams than the page size should + all those teams on one page. + Given I am enrolled in a course with a team configuration and a topic + When I visit the Teams page for that topic + Then I should see the correct page header + And I should see a pagination header showing the number of teams + And I should see all the expected team cards + And I should see a button to add a team + And I should not see a pagination footer + """ + teams = self.create_teams(self.TEAMS_PAGE_SIZE) + 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.verify_teams(teams) + self.assertFalse( + self.browse_teams_page.pagination_controls_visible(), + msg='Expected paging footer to be invisible' + ) + + def test_teams_navigation_buttons(self): + """ + Scenario: The user should be able to page through a topic's team list + using navigation buttons when it is longer than the page size. + Given I am enrolled in a course with a team configuration and a topic + When I visit the Teams page for that topic + Then I should see the correct page header + And I should see that I am on the first page of results + When I click on the next page button + Then I should see that I am on the second page of results + 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.TEAMS_PAGE_SIZE + 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.browse_teams_page.press_next_page_button() + self.verify_on_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) + + def test_teams_page_input(self): + """ + Scenario: The user should be able to page through a topic's team list + using the page input when it is longer than the page size. + Given I am enrolled in a course with a team configuration and a topic + When I visit the Teams page for that topic + Then I should see the correct page header + And I should see that I am on the first page of results + When I input the second page + Then I should see that I am on the second page of results + When I input the first page + Then I should see that I am on the first page of results + """ + teams = self.create_teams(self.TEAMS_PAGE_SIZE + 10) + self.browse_teams_page.visit() + self.verify_page_header() + self.verify_on_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.browse_teams_page.go_to_page(1) + self.verify_on_page(1, teams, 'Showing 1-10 out of 20 total', True) + + def test_teams_membership(self): + """ + Scenario: Team cards correctly reflect membership of the team. + Given I am enrolled in a course with a team configuration and a topic + containing one team + And I add myself to the team + When I visit the Teams page for that topic + Then I should see the correct page header + And I should see the team for that topic + And I should see that the team card shows my membership + """ + teams = self.create_teams(1) + self.browse_teams_page.visit() + self.verify_page_header() + self.verify_teams(teams) + self.create_membership(self.user_info['username'], teams[0]['id']) + self.browser.refresh() + self.browse_teams_page.wait_for_ajax() + self.assertEqual( + self.browse_teams_page.team_cards[0].find_element_by_css_selector('.member-count').text, + '1 / 10 Members' + ) diff --git a/common/test/acceptance/tests/studio/test_studio_home.py b/common/test/acceptance/tests/studio/test_studio_home.py index 747bc7aeb8..ff4211783e 100644 --- a/common/test/acceptance/tests/studio/test_studio_home.py +++ b/common/test/acceptance/tests/studio/test_studio_home.py @@ -3,7 +3,6 @@ Acceptance tests for Home Page (My Courses / My Libraries). """ from bok_choy.web_app_test import WebAppTest from opaque_keys.edx.locator import LibraryLocator -from unittest import skip from ...pages.studio.auto_auth import AutoAuthPage from ...pages.studio.library import LibraryEditPage diff --git a/common/test/acceptance/tests/studio/test_studio_library.py b/common/test/acceptance/tests/studio/test_studio_library.py index 28fd99800a..0086024f69 100644 --- a/common/test/acceptance/tests/studio/test_studio_library.py +++ b/common/test/acceptance/tests/studio/test_studio_library.py @@ -2,7 +2,6 @@ Acceptance tests for Content Libraries in Studio """ from ddt import ddt, data -from unittest import skip from nose.plugins.attrib import attr from flaky import flaky diff --git a/common/test/acceptance/tests/studio/test_studio_outline.py b/common/test/acceptance/tests/studio/test_studio_outline.py index 3d156d9515..c3eda18e1b 100644 --- a/common/test/acceptance/tests/studio/test_studio_outline.py +++ b/common/test/acceptance/tests/studio/test_studio_outline.py @@ -141,13 +141,16 @@ class WarningMessagesTest(CourseOutlineTest): FUTURE_UNPUBLISHED_WARNING = 'Unpublished changes to content that will release in the future' NEVER_PUBLISHED_WARNING = 'Unpublished units will not be released' - class PublishState: + class PublishState(object): + """ + Default values for representing the published state of a unit + """ NEVER_PUBLISHED = 1 UNPUBLISHED_CHANGES = 2 PUBLISHED = 3 VALUES = [NEVER_PUBLISHED, UNPUBLISHED_CHANGES, PUBLISHED] - class UnitState: + class UnitState(object): """ Represents the state of a unit """ def __init__(self, is_released, publish_state, is_locked): diff --git a/common/test/acceptance/tests/studio/test_studio_settings.py b/common/test/acceptance/tests/studio/test_studio_settings.py index a51c3148c3..39eed95996 100644 --- a/common/test/acceptance/tests/studio/test_studio_settings.py +++ b/common/test/acceptance/tests/studio/test_studio_settings.py @@ -14,7 +14,6 @@ from ...pages.studio.settings import SettingsPage from ...pages.studio.settings_advanced import AdvancedSettingsPage from ...pages.studio.settings_group_configurations import GroupConfigurationsPage from ...pages.lms.courseware import CoursewarePage -from unittest import skip from textwrap import dedent from xmodule.partitions.partitions import Group diff --git a/common/test/acceptance/tests/studio/test_studio_settings_certificates.py b/common/test/acceptance/tests/studio/test_studio_settings_certificates.py index ced72eb795..76986d040a 100644 --- a/common/test/acceptance/tests/studio/test_studio_settings_certificates.py +++ b/common/test/acceptance/tests/studio/test_studio_settings_certificates.py @@ -1,6 +1,7 @@ """ Acceptance tests for Studio's Setting pages """ +from unittest import skip from .base_studio_test import StudioCourseTest from ...pages.studio.settings_certificates import CertificatesPage @@ -9,8 +10,8 @@ class CertificatesTest(StudioCourseTest): """ Tests for settings/certificates Page. """ - def setUp(self, is_staff=False): - super(CertificatesTest, self).setUp(is_staff) + def setUp(self): # pylint: disable=arguments-differ + super(CertificatesTest, self).setUp(is_staff=True) self.certificates_page = CertificatesPage( self.browser, self.course_info['org'], @@ -105,6 +106,7 @@ class CertificatesTest(StudioCourseTest): self.assertIn("Updated Course Title Override 2", certificate.course_title) + @skip # TODO fix this, see SOL-1053 def test_can_delete_certificate(self): """ Scenario: Ensure that the user can delete certificate. @@ -126,9 +128,11 @@ class CertificatesTest(StudioCourseTest): self.assertEqual(len(self.certificates_page.certificates), 1) - # Delete certificate - certificate.delete_certificate() + # Delete the certificate we just created + certificate.click_delete_certificate_button() + self.certificates_page.click_confirmation_prompt_primary_button() + # Reload the page and confirm there are no certificates self.certificates_page.visit() self.assertEqual(len(self.certificates_page.certificates), 0) diff --git a/common/test/acceptance/tests/studio/test_studio_split_test.py b/common/test/acceptance/tests/studio/test_studio_split_test.py index cedb89ed44..7c125bb104 100644 --- a/common/test/acceptance/tests/studio/test_studio_split_test.py +++ b/common/test/acceptance/tests/studio/test_studio_split_test.py @@ -2,7 +2,6 @@ Acceptance tests for Studio related to the split_test module. """ -import json import math from unittest import skip from nose.plugins.attrib import attr diff --git a/common/test/acceptance/tests/test_annotatable.py b/common/test/acceptance/tests/test_annotatable.py index fc9beed182..0e470da265 100644 --- a/common/test/acceptance/tests/test_annotatable.py +++ b/common/test/acceptance/tests/test_annotatable.py @@ -2,8 +2,6 @@ """ E2E tests for the LMS. """ -import time - from unittest import skip from .helpers import UniqueCourseTest @@ -11,7 +9,6 @@ from ..pages.studio.auto_auth import AutoAuthPage from ..pages.lms.courseware import CoursewarePage from ..pages.lms.annotation_component import AnnotationComponentPage from ..fixtures.course import CourseFixture, XBlockFixtureDesc -from ..fixtures.xqueue import XQueueResponseFixture from textwrap import dedent diff --git a/common/test/acceptance/tests/video/test_video_events.py b/common/test/acceptance/tests/video/test_video_events.py index f851a02bca..ec7bceaa30 100644 --- a/common/test/acceptance/tests/video/test_video_events.py +++ b/common/test/acceptance/tests/video/test_video_events.py @@ -3,6 +3,7 @@ import datetime import json import ddt +from unittest import skip from ..helpers import EventsTestMixin from .test_video_module import VideoBaseTest @@ -195,6 +196,7 @@ class VideoBumperEventsTest(VideoEventsTestMixin): ('edx.video.bumper.stopped', wait_for_state) ) @ddt.unpack + @skip("Failing on master; To see remove is_youtube_available() form base class") def test_video_control_events(self, event_type, action): """ Scenario: Video component with pre-roll emits events correctly @@ -285,6 +287,7 @@ class VideoBumperEventsTest(VideoEventsTestMixin): } self.assert_events_match([expected_event], [video_event]) + @skip("Failing on master; To see remove is_youtube_available() form base class") def test_strict_event_format(self): """ This test makes a very strong assertion about the fields present in events. The goal of it is to ensure that new diff --git a/common/test/acceptance/tests/video/test_video_module.py b/common/test/acceptance/tests/video/test_video_module.py index 48ee3b5dd8..16ef14e19a 100644 --- a/common/test/acceptance/tests/video/test_video_module.py +++ b/common/test/acceptance/tests/video/test_video_module.py @@ -404,6 +404,7 @@ class YouTubeVideoTest(VideoBaseTest): self.assertTrue(self.video.is_video_rendered('html5')) + @skip('Failing on master; To see remove is_youtube_available() form base class') def test_download_transcript_button_works_correctly(self): """ Scenario: Download Transcript button works correctly @@ -712,6 +713,7 @@ class YouTubeVideoTest(VideoBaseTest): self.assertEqual(self.video.caption_languages, {'zh_HANS': 'Simplified Chinese', 'zh_HANT': 'Traditional Chinese'}) + @skip('Failing on master; To see remove is_youtube_available() form base class') def test_video_bumper_render(self): """ Scenario: Multiple videos with bumper in sequentials all load and work, switching between sequentials diff --git a/conf/locale/ar/LC_MESSAGES/django.mo b/conf/locale/ar/LC_MESSAGES/django.mo index 4a0704e47a..a07e6f0b44 100644 Binary files a/conf/locale/ar/LC_MESSAGES/django.mo and b/conf/locale/ar/LC_MESSAGES/django.mo differ diff --git a/conf/locale/ar/LC_MESSAGES/django.po b/conf/locale/ar/LC_MESSAGES/django.po index 51f83e97fc..fe9ba11eeb 100644 --- a/conf/locale/ar/LC_MESSAGES/django.po +++ b/conf/locale/ar/LC_MESSAGES/django.po @@ -125,10 +125,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:33+0000\n" +"POT-Creation-Date: 2015-07-22 17:45+0000\n" "PO-Revision-Date: 2015-06-30 03:58+0000\n" "Last-Translator: Nabeel El-Dughailib \n" -"Language-Team: Arabic (http://www.transifex.com/p/edx-platform/language/ar/)\n" +"Language-Team: Arabic (http://www.transifex.com/projects/p/edx-platform/language/ar/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -150,8 +150,6 @@ msgstr "المناقشة" #: cms/djangoapps/contentstore/views/component.py #: lms/djangoapps/class_dashboard/dashboard_data.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Problem" msgstr "المسألة " @@ -252,6 +250,68 @@ msgid "" " Please list each domain on its own line." msgstr "" +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "الوضعية" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html +msgid "Course" +msgstr "المساق " + +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/annotatable_module.py +#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/combined_open_ended_module.py +#: common/lib/xmodule/xmodule/discussion_module.py +#: common/lib/xmodule/xmodule/html_module.py +#: common/lib/xmodule/xmodule/imageannotation_module.py +#: common/lib/xmodule/xmodule/library_content_module.py +#: common/lib/xmodule/xmodule/lti_module.py +#: common/lib/xmodule/xmodule/peer_grading_module.py +#: common/lib/xmodule/xmodule/split_test_module.py +#: common/lib/xmodule/xmodule/textannotation_module.py +#: common/lib/xmodule/xmodule/videoannotation_module.py +#: common/lib/xmodule/xmodule/word_cloud_module.py +#: cms/templates/container.html cms/templates/library.html +msgid "Display Name" +msgstr "اسم العرض" + +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "السعر " + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "شهادة ميثاق الشرف الأكاديمي" @@ -619,11 +679,9 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" -"إذا لم يكن لديك حساب لدى {platform_name} بعد، انقر رجاءً على سجّل " -"الآن في أعلى الصفحة." #: common/djangoapps/student/views.py msgid "There was an error receiving your login information. Please email us." @@ -1654,23 +1712,6 @@ msgstr "لم يمكن تفسير ’{given_answer}‘ بشكل عدد." msgid "XML data for the annotation" msgstr "بيانات XML للملاحظات التوضيحية" -#: common/lib/xmodule/xmodule/annotatable_module.py -#: common/lib/xmodule/xmodule/capa_base.py -#: common/lib/xmodule/xmodule/combined_open_ended_module.py -#: common/lib/xmodule/xmodule/discussion_module.py -#: common/lib/xmodule/xmodule/html_module.py -#: common/lib/xmodule/xmodule/imageannotation_module.py -#: common/lib/xmodule/xmodule/library_content_module.py -#: common/lib/xmodule/xmodule/lti_module.py -#: common/lib/xmodule/xmodule/peer_grading_module.py -#: common/lib/xmodule/xmodule/split_test_module.py -#: common/lib/xmodule/xmodule/textannotation_module.py -#: common/lib/xmodule/xmodule/videoannotation_module.py -#: common/lib/xmodule/xmodule/word_cloud_module.py -#: cms/templates/container.html cms/templates/library.html -msgid "Display Name" -msgstr "اسم العرض" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1796,13 +1837,9 @@ msgstr "الترتيب العشوائي" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" -"تحدِّد هذه القيمة عدد مرّات ترتيب المدخلات عشوائيًّا عندما يحمّل الطالب " -"المسألة. ولا ينطبق هذا الإعداد سوى على المسائل التي قد تتضمّن قيم رقمية جرى " -"توليدها عشوائيًّا. ويمكن ضبط قيمة افتراضية من خلال الإعدادات المتقدّمة." #: common/lib/xmodule/xmodule/capa_base.py msgid "On Reset" @@ -3326,10 +3363,6 @@ msgstr "" msgid "Library Version" msgstr "" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "الوضعية" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "لتحديد كيفية استخراج المحتوى من المكتبة" @@ -3961,15 +3994,12 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" -"تحدِّد هذه القيمة عدد مرّات ترتيب القيم المتغيّرة في مسألة ما عشوائيًّا " -"عندما يحمّل الطالب المسألة. والقيم الصحيحة هي \"دائمًا\"، و\"جاري إعادة " -"الضبط\"، و\"أبدًا\"، و\"لكل طالب\". ولا ينطبق هذا الإعداد سوى على المسائل " -"التي قد وَلّدت قيمًا رقمية عشوائيًّا. " #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "Days Early for Beta Users" @@ -5046,7 +5076,7 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" @@ -5163,6 +5193,34 @@ msgstr "" msgid "Visit a course wiki to add an article." msgstr "تفضّل بزيارة إحدى صفحات الويكي الخاصة بالمساق لتضيف مقالًا. " +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" + #: lms/djangoapps/courseware/tabs.py #: lms/templates/courseware/courseware-error.html msgid "Courseware" @@ -5836,7 +5894,6 @@ msgstr "الجنس" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/tasks_helper.py -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Level of Education" msgstr "المستوى التعليمي " @@ -5856,28 +5913,22 @@ msgstr "المجموعة" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5937,29 +5988,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -6013,28 +6063,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -6168,13 +6218,12 @@ msgid "Data Download" msgstr "تنزيل البيانات" #: lms/djangoapps/instructor/views/instructor_dashboard.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Analytics" -msgstr "التحليلات" +msgid "For analytics about your course, go to {analytics_dashboard_name}." +msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." -msgstr "تتوافر البيانات السكّانية الآن على {dashboard_link}." +msgid "Analytics" +msgstr "التحليلات" #: lms/djangoapps/instructor/views/instructor_dashboard.py #: lms/templates/courseware/legacy_instructor_dashboard.html @@ -6456,7 +6505,6 @@ msgid "Title" msgstr "العنوان" #: lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "سنة الميلاد" @@ -7119,10 +7167,6 @@ msgstr "التعليقات" msgid "University" msgstr "الجامعة" -#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html -msgid "Course" -msgstr "المساق " - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "تاريخ الإعلان عن المساق " @@ -7931,6 +7975,10 @@ msgstr "" msgid "course_id must be provided" msgstr "" +#: lms/djangoapps/teams/views.py +msgid "The supplied topic id {topic_id} is not valid" +msgstr "" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "" @@ -7940,11 +7988,11 @@ msgid "last_activity is not yet supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The supplied course_id {course_id} is not valid." +msgid "The ordering {} is not supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The ordering {} is not supported" +msgid "The supplied course_id {course_id} is not valid." msgstr "" #: lms/djangoapps/teams/views.py @@ -7997,6 +8045,16 @@ msgstr "لم يكن وجهك مرئيًّا في صورتك الذاتية." msgid "There was an error verifying your ID photos." msgstr "نأسف لحدوث خطأ أثناء التحقّق من صور بطاقتك الشخصية." +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "المقدّمة " @@ -8834,6 +8892,10 @@ msgstr "" msgid "A cohort with the same name already exists." msgstr "" +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -8881,6 +8943,20 @@ msgid "" "credit provider." msgstr "" +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "" @@ -9506,9 +9582,7 @@ msgstr "هذه الصفحة غير موجودة" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -9646,6 +9720,11 @@ msgstr "" msgid "Course Navigation" msgstr "تصفّح المساق" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py msgid "Help" @@ -9809,7 +9888,8 @@ msgstr "" msgid "Starts" msgstr "" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "لوحة المعلومات" @@ -9838,11 +9918,11 @@ msgid "Clear search" msgstr "" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" +msgid "Find New Courses" msgstr "" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." +msgid "Account Status Info" msgstr "" #: lms/templates/dashboard.html @@ -10463,12 +10543,7 @@ msgid "More options dropdown" msgstr "قائمة منسدلة لخيارات إضافية" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" +msgid "Profile" msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html @@ -10476,14 +10551,15 @@ msgstr "" msgid "Shopping Cart" msgstr "سلّة التسوّق" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" -msgstr "تسجيل" - #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "Sign in" msgstr "تسجيل الدخول" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +#: lms/templates/register.html +msgid "Register" +msgstr "تسجيل" + #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "" "Warning: Your browser is not fully supported. We strongly " @@ -10505,10 +10581,6 @@ msgstr "" msgid "Schools" msgstr "المدارس" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "سجِّل الآن" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -11570,6 +11642,11 @@ msgstr "" msgid "I completed the {course_title} course on {platform_name}." msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "" @@ -11578,6 +11655,15 @@ msgstr "" msgid "Post on Facebook" msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "" @@ -11834,6 +11920,10 @@ msgstr "{chapter}، الفصل الحالي " msgid "due {date}" msgstr "تاريخ الاستحقاق {date}" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "" + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -11937,10 +12027,6 @@ msgstr "تنتهي الحصص" msgid "Estimated Effort" msgstr "الجهد المقدَّر" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "السعر " - #: lms/templates/courseware/course_about.html msgid "Prerequisites" msgstr "المتطلّبات الأساسية" @@ -11971,13 +12057,25 @@ msgstr "" msgid "View this course as:" msgstr "مشاهدة هذا المساق كـ:" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "التلميذ في {content_group}" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" -msgstr "ضبط وضعية المعاينة" +msgid "Username or email:" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." +msgstr "" #: lms/templates/courseware/course_navigation.html msgid "Course Material" @@ -12013,6 +12111,10 @@ msgstr "استكشف المساقات التي تقدّمها {platform_name}." msgid "{platform_name} Logo" msgstr "شعار {platform_name}" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "" @@ -12309,78 +12411,6 @@ msgstr "" "لإرسال بريد إلكتروني، يُرجى زيارة قسم \"البريد الإلكتروني\" في لوحة معلومات " "الأستاذ." -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "عذرًا، ليس هناك من تحليلات متوفّرة حاليًّا." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "أنشطة الطالب اليومية" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "اليوم " - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "الطلّاب " - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "توزيع الدرجات على المسائل" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "الحد الأقصى" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "النقاط المحرَزة (Num Students) " - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "ليس هناك من بيانات متاحة للعرض حاليًّا." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "" -"جاري تحميل آخر الرسومات البيانية لك؛ وقد يستغرق هذا بعض الوقت بناءً على حجم " -"صفّك." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "عدد الطلّاب الذين فتحوا قسمًا فرعيًّا" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr "توزيع الدرجات لكل مسألة" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "لا توجد مسائل في هذا القسم." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "الطلّاب الذين قدّموا إجابات صحيحة" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "عدد الطلّاب " - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" -" توزيع الطلّاب في كل بلد، بالنسبة لكافة المساقات، بين 12 سبتمبر و17 أكتوبر، " -"عبر الخادم 1 (بالشكل الموضَّح هنا كمثال):" - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "مهام الأستاذ المعلَّقة " @@ -12548,11 +12578,12 @@ msgid "Requirements for Course Credit" msgstr "" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." +msgid "{student_name}, you are no longer eligible for credit in this course." msgstr "" #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." +msgid "" +"{student_name}, you have met the requirements for credit in this course." msgstr "" #: lms/templates/courseware/progress.html @@ -12619,6 +12650,46 @@ msgstr "" "لقد زرتَ مؤخّرًا القسم {section_link}. فإذا انتهيت من العمل فيه، يُرجى " "اختيار قسم آخر على الجهة اليسرى. " +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "مرحبًا {name}،" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "" + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -12752,10 +12823,6 @@ msgstr "" msgid "I'm learning on {platform_name}:" msgstr "" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "" @@ -13699,11 +13766,6 @@ msgstr "" msgid "You have been invited to a beta test for {course_name}" msgstr "جرت دعوتك لاختبار النسخة التجريبية للمساق {course_name}" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "مرحبًا {name}،" - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "شكرًا لشرائك" @@ -15218,34 +15280,6 @@ msgstr "" msgid "Send me a copy of the invoice" msgstr "أرسل لي نسخة من الفاتورة" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "توزيع الدرجات" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "" -"يعرض الجدول أدناه توزيع الدرجات لكل من المسائل المعيارية في فصلك، وقد تم " -"تحديدها بالرابط الخاص بالمسألة." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "" -"تظهر الدرجات دون تطبيق الأوزان النسبية عليها، بالتالي فإذا كانت مسألتك تتضمن" -" 2 سؤال، ستظهر وكأنها تحمل 2 نقطة كرقمٍ إجمالي." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "تحميل قائمة المسائل... " - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "توزيع الجنسين " - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "لوحة المعلومات الخاصة بموجّه المساق" @@ -15472,6 +15506,10 @@ msgstr "" msgid "Add CCX Coach" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "ليس هناك من بيانات متاحة للعرض حاليًّا." + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "استخدام \"إعادة تحميل الرسوم البيانية\" لتحديث الرسوم البيانية." @@ -15524,6 +15562,10 @@ msgstr "" msgid "Download Problem Data for all Problems as a CSV" msgstr "تنزيل بيانات المسألة لكلّ المسائل بصيغة ملف CSV" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr "توزيع الدرجات لكل مسألة" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "تنزيل الطلاب المسجلين بصيغة CSV" @@ -15536,6 +15578,10 @@ msgstr "تنزيل درجات الطلاب بصيغة CSV" msgid "This is a partial list, to view all students download as a csv." msgstr "هذه قائمة جزئية، لعرض جميع الطلاب يرجى التنزيل بصيغة CSV." +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "لا توجد مسائل في هذا القسم." + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "إرسال بريد إلكتروني" @@ -16350,6 +16396,10 @@ msgstr "السعر لكل طالب:" msgid "Discount Applied:" msgstr "الخصم المطبَّق:" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "الطلّاب " + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -16606,6 +16656,10 @@ msgstr "" msgid "Currently the {platform_name} servers are overloaded" msgstr "تعمل مخدمات المنصة {platform_name} حالياً بمستوى تحميل يتجاوز طاقتها" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "" @@ -16714,16 +16768,26 @@ msgstr "حدث الخاطئ التالي أثناء تعديل إسمك:" msgid "Re-Verify for {course_name}" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." msgstr "" +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" + #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." msgstr "" @@ -19988,10 +20052,6 @@ msgstr "تصدير" msgid "Current Library:" msgstr "المكتبة الحالية:" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "" diff --git a/conf/locale/ar/LC_MESSAGES/djangojs.mo b/conf/locale/ar/LC_MESSAGES/djangojs.mo index f2b169b3fb..219b1d5392 100644 Binary files a/conf/locale/ar/LC_MESSAGES/djangojs.mo and b/conf/locale/ar/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/ar/LC_MESSAGES/djangojs.po b/conf/locale/ar/LC_MESSAGES/djangojs.po index bfadb49398..c4042770c2 100644 --- a/conf/locale/ar/LC_MESSAGES/djangojs.po +++ b/conf/locale/ar/LC_MESSAGES/djangojs.po @@ -75,10 +75,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:31+0000\n" -"PO-Revision-Date: 2015-07-10 19:12+0000\n" +"POT-Creation-Date: 2015-07-22 17:43+0000\n" +"PO-Revision-Date: 2015-07-14 14:36+0000\n" "Last-Translator: Sarina Canelake \n" -"Language-Team: Arabic (http://www.transifex.com/p/edx-platform/language/ar/)\n" +"Language-Team: Arabic (http://www.transifex.com/projects/p/edx-platform/language/ar/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2407,14 +2407,36 @@ msgstr "العلامات: " msgid "name" msgstr "الاسم " +#: lms/djangoapps/teams/static/teams/js/collections/team.js +msgid "open_slots" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/collections/topic.js msgid "team count" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: 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/teams.js +msgid "Create new team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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 @@ -2429,6 +2451,14 @@ msgstr "" msgid "Browse" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "" + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2487,22 +2517,6 @@ msgstr "نأسف لحدوث خطأ في استحداث الدرجات. يُرج msgid "Error generating problem grade report. Please try again." msgstr "" -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "العرض المتري غير متوفّر الآن." - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "نأسف لحدوث خطأ في إحضار بيانات توزيع الدرجات." - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "التحديث الأخير: <%= timestamp %>" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "جرى تقييم أعمال <%= num_students %> طالبًا." - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3312,6 +3326,16 @@ msgstr "تعذّر تقديم تبرعك." msgid "An error occurred. Please try again later." msgstr "ناسف لحدوث خطأ. يُرجى إعادة المحاولة لاحقًا. " +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "" @@ -3324,8 +3348,8 @@ msgstr "نأسف لحدوث خطأ. يُرجى المحاولة مجدّدًا." msgid "Focus grabber" msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." @@ -3333,6 +3357,22 @@ msgstr "" "نأسف لحدوث خطأ. يُرجى التأكّد من أنّ حاسوبك متّصل بالإنترنت، ثمّ حاول إعادة " "فتح الصفحة. " +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "إخفاء الملاحظات" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "إظهار الملاحظات" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3342,22 +3382,6 @@ msgstr "يُرجى إدخال كلمة في %(anchor_start)s حقل البحث%( msgid "Current tab" msgstr "التبويبة الحالية" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "إخفاء الملاحظات" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "إظهار الملاحظات" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "الموقع في المساق" @@ -5169,6 +5193,21 @@ msgstr "" msgid "remove" msgstr "" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "" @@ -5265,10 +5304,6 @@ msgstr "" msgid "LEARN MORE" msgstr "اعرف المزيد" -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "" - #: lms/templates/discovery/result_item.underscore msgid "Starts" msgstr "" @@ -6218,10 +6253,6 @@ msgstr "الحالة" msgid "Common Problem Types" msgstr "أنواع المسائل الشائعة" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "إضافة مكوِّن جديد" diff --git a/conf/locale/eo/LC_MESSAGES/django.mo b/conf/locale/eo/LC_MESSAGES/django.mo index b613a99712..048d01f0a5 100644 Binary files a/conf/locale/eo/LC_MESSAGES/django.mo and b/conf/locale/eo/LC_MESSAGES/django.mo differ diff --git a/conf/locale/eo/LC_MESSAGES/django.po b/conf/locale/eo/LC_MESSAGES/django.po index 63b36d52d1..f6a4d3d352 100644 --- a/conf/locale/eo/LC_MESSAGES/django.po +++ b/conf/locale/eo/LC_MESSAGES/django.po @@ -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-07-13 04:42+0000\n" -"PO-Revision-Date: 2015-07-13 04:42:08.333956\n" +"POT-Creation-Date: 2015-07-22 18:12+0000\n" +"PO-Revision-Date: 2015-07-22 18:12:54.680330\n" "Last-Translator: \n" "Language-Team: openedx-translation \n" "MIME-Version: 1.0\n" @@ -62,8 +62,6 @@ msgstr "Dïsçüssïön Ⱡ'σяєм ιρѕυм ∂σłσ#" #: cms/djangoapps/contentstore/views/component.py #: lms/djangoapps/class_dashboard/dashboard_data.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Problem" msgstr "Prößlém Ⱡ'σяєм ιρѕυм #" @@ -171,6 +169,93 @@ msgstr "" "Lïst öf dömäïns thät äré ällöwéd tö mäké çröss-dömäïn réqüésts tö thïs sïté." " Pléäsé lïst éäçh dömäïn ön ïts öwn lïné. Ⱡ'σяєм ιρѕυм #" +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "Mödé Ⱡ'σяєм ι#" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "Vérïfïçätïön Déädlïné Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" +"ÖPTÌÖNÀL: Àftér thïs däté/tïmé, üsérs wïll nö löngér ßé äßlé tö süßmït " +"phötös för vérïfïçätïön. Thïs äppïés ÖNLÝ tö mödés thät réqüïré " +"vérïfïçätïön. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂" +" ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ " +"мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ " +"єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє " +"νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт " +"¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηι#" + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html +msgid "Course" +msgstr "Çöürsé Ⱡ'σяєм ιρѕυ#" + +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/annotatable_module.py +#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/combined_open_ended_module.py +#: common/lib/xmodule/xmodule/discussion_module.py +#: common/lib/xmodule/xmodule/html_module.py +#: common/lib/xmodule/xmodule/imageannotation_module.py +#: common/lib/xmodule/xmodule/library_content_module.py +#: common/lib/xmodule/xmodule/lti_module.py +#: common/lib/xmodule/xmodule/peer_grading_module.py +#: common/lib/xmodule/xmodule/split_test_module.py +#: common/lib/xmodule/xmodule/textannotation_module.py +#: common/lib/xmodule/xmodule/videoannotation_module.py +#: common/lib/xmodule/xmodule/word_cloud_module.py +#: cms/templates/container.html cms/templates/library.html +msgid "Display Name" +msgstr "Dïspläý Nämé Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#" + +#: common/djangoapps/course_modes/models.py +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "Prïçé Ⱡ'σяєм ιρѕ#" + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "Ûpgrädé Déädlïné Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" +"ÖPTÌÖNÀL: Àftér thïs däté/tïmé, üsérs wïll nö löngér ßé äßlé tö énröll ïn " +"thïs mödé. Léävé thïs ßlänk ïf üsérs çän énröll ïn thïs mödé üntïl " +"énröllmént çlösés för thé çöürsé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя " +"α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα" +" αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ " +"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη " +"яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα " +"ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα#" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" +"ÖPTÌÖNÀL: Thïs ïs thé SKÛ (stöçk kéépïng ünït) öf thïs mödé ïn thé éxtérnäl " +"éçömmérçé sérvïçé. Léävé thïs ßlänk ïf thé çöürsé häs nöt ýét ßéén mïgrätéd" +" tö thé éçömmérçé sérvïçé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя " +"α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα" +" αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ " +"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη " +"яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα " +"ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη #" + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "Hönör Çödé Çértïfïçäté Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢#" @@ -618,11 +703,12 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" -"Ìf ýöü dön't hävé än {platform_name} äççöünt ýét, çlïçk Régïstér " -"Nöw ät thé töp öf thé pägé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#" +"Ìf ýöü dön't hävé än {platform_name} äççöünt ýét, çlïçk " +"Régïstér ät thé töp öf thé pägé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт " +"αмєт, ¢σηѕє¢тє#" #: common/djangoapps/student/views.py msgid "There was an error receiving your login information. Please email us." @@ -1755,23 +1841,6 @@ msgstr "" msgid "XML data for the annotation" msgstr "XML dätä för thé ännötätïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#" -#: common/lib/xmodule/xmodule/annotatable_module.py -#: common/lib/xmodule/xmodule/capa_base.py -#: common/lib/xmodule/xmodule/combined_open_ended_module.py -#: common/lib/xmodule/xmodule/discussion_module.py -#: common/lib/xmodule/xmodule/html_module.py -#: common/lib/xmodule/xmodule/imageannotation_module.py -#: common/lib/xmodule/xmodule/library_content_module.py -#: common/lib/xmodule/xmodule/lti_module.py -#: common/lib/xmodule/xmodule/peer_grading_module.py -#: common/lib/xmodule/xmodule/split_test_module.py -#: common/lib/xmodule/xmodule/textannotation_module.py -#: common/lib/xmodule/xmodule/videoannotation_module.py -#: common/lib/xmodule/xmodule/word_cloud_module.py -#: cms/templates/container.html cms/templates/library.html -msgid "Display Name" -msgstr "Dïspläý Nämé Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1905,18 +1974,17 @@ msgstr "Rändömïzätïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" -"Défïnés höw öftén ïnpüts äré rändömïzéd whén ä stüdént löäds thé prößlém. " -"Thïs séttïng önlý äpplïés tö prößléms thät çän hävé rändömlý générätéd " -"nümérïç välüés. À défäült välüé çän ßé sét ïn Àdvänçéd Séttïngs. Ⱡ'σяєм " -"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя " -"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ " -"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ " +"Défïnés whén tö rändömïzé thé värïäßlés spéçïfïéd ïn thé ässöçïätéd Pýthön " +"sçrïpt. För prößléms thät dö nöt rändömïzé välüés, spéçïfý \"Névér\". " +"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ " +"тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм," +" qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ " "¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє " -"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя#" +"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт " +"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕ#" #: common/lib/xmodule/xmodule/capa_base.py msgid "On Reset" @@ -3760,10 +3828,6 @@ msgstr "" msgid "Library Version" msgstr "Lïßrärý Vérsïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "Mödé Ⱡ'σяєм ι#" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "" @@ -4547,19 +4611,19 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" -"Spéçïfý höw öftén värïäßlé välüés ïn ä prößlém äré rändömïzéd whén ä stüdént" -" löäds thé prößlém. Välïd välüés äré \"älwäýs\", \"önrését\", \"névér\", änd" -" \"pér_stüdént\". Thïs séttïng önlý äpplïés tö prößléms thät hävé rändömlý " -"générätéd nümérïç välüés. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя " +"Spéçïfý thé défäült för höw öftén värïäßlé välüés ïn ä prößlém äré " +"rändömïzéd. Thïs séttïng shöüld ßé sét tö \"névér\" ünléss ýöü plän tö " +"prövïdé ä Pýthön sçrïpt tö ïdéntïfý änd rändömïzé välüés ïn möst öf thé " +"prößléms ïn ýöür çöürsé. Välïd välüés äré \"älwäýs\", \"önrését\", " +"\"névér\", änd \"pér_stüdént\". Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя " "α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα" -" αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ " -"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη " -"яєρяєнєη∂єяιт ιη νσłυρтαтє#" +" αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση#" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "Days Early for Beta Users" @@ -5905,7 +5969,7 @@ msgstr "Çértïfïçäté Välïdätïön Ⱡ'σяєм ιρѕυм ∂σłσя #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" @@ -6042,6 +6106,42 @@ msgstr "" "Vïsït ä çöürsé wïkï tö ädd än ärtïçlé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " "¢σηѕє¢тєтυя#" +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "Çöürsé döés nöt stärt üntïl {} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "Ýöü hävé ünfülfïlléd mïléstönés Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "" +"Ýöü dö nöt hävé äççéss tö thïs çöürsé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " +"¢σηѕє¢тєтυ#" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "" +"Ýöü dö nöt hävé äççéss tö thïs çöürsé ön ä mößïlé dévïçé Ⱡ'σяєм ιρѕυм ∂σłσя " +"ѕιт αмєт, ¢σηѕє¢тєтυя α#" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" +"Théré ïs nö üsér wïth thé üsérnämé ör émäïl äddréss {user_name} énrölléd ïn " +"thïs çöürsé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" +"Thïs týpé öf çömpönént çännöt ßé shöwn whïlé vïéwïng thé çöürsé äs ä " +"spéçïfïç stüdént. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#" + #: lms/djangoapps/courseware/tabs.py #: lms/templates/courseware/courseware-error.html msgid "Courseware" @@ -6783,7 +6883,6 @@ msgstr "Géndér Ⱡ'σяєм ιρѕυ#" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/tasks_helper.py -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Level of Education" msgstr "Lévél öf Édüçätïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#" @@ -6803,61 +6902,41 @@ msgstr "Çöhört Ⱡ'σяєм ιρѕυ#" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" -"Ýöür énrölléd stüdént pröfïlé répört ïs ßéïng générätéd! Ýöü çän vïéw thé " -"stätüs öf thé générätïön täsk ïn thé 'Péndïng Täsks' séçtïön. Ⱡ'σяєм ιρѕυм " -"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя " -"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ " -"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ " -"¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє " -"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт " -"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт łαвσяυ#" +"Thé énrölléd léärnér pröfïlé répört ïs ßéïng çréätéd. Tö vïéw thé stätüs öf " +"thé répört, séé Péndïng Ìnstrüçtör Täsks ßélöw. Ⱡ'σяєм ιρ#" #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" -"Àn énrölléd stüdént pröfïlé 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 єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя " -"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ " -"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ " -"¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє " -"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢є#" +"Thïs énröllmént répört ïs çürréntlý ßéïng çréätéd. Tö vïéw thé stätüs öf thé" +" répört, séé Péndïng Ìnstrüçtör Täsks ßélöw. Ýöü wïll ßé äßlé tö döwnlöäd " +"thé répört whén ït ïs çömplété. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя " +"α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα" +" αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ " +"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη " +"яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα " +"ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт#" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" -"Ýöür stüdénts whö mäý énröll répört ïs ßéïng générätéd! Ýöü çän vïéw thé " -"stätüs öf thé générätïön täsk ïn thé 'Péndïng Täsks' séçtïön. Ⱡ'σяєм ιρѕυм " -"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя " -"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ " -"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ " -"¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє " -"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт " -"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт łαвσяυм#" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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 "" -"À stüdénts whö mäý énröll 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 єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя " -"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ " -"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ " -"¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє " -"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтє#" +"Thé énröllmént répört ïs ßéïng çréätéd. Thïs répört çöntäïns ïnförmätïön " +"äßöüt léärnérs whö çän énröll ïn thé çöürsé. Tö vïéw thé stätüs öf thé " +"répört, séé Péndïng Ìnstrüçtör Täsks ßélöw. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " +"¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт " +"∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση " +"υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє " +"∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα" +" ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂#" #: lms/djangoapps/instructor/views/api.py msgid "The file must contain a 'cohort' column containing cohort names." @@ -6919,49 +6998,49 @@ msgstr "Tötäl Dïsçöüntéd Àmöünt Ⱡ'σяєм ιρѕυм ∂σłσя ѕ #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" -"Ýöür détäïléd énröllmént répört ïs ßéïng générätéd! Ýöü çän vïéw thé stätüs " -"öf thé générätïön täsk ïn thé 'Péndïng Täsks' séçtïön. Ⱡ'#" +"Thé détäïléd énröllmént répört ïs ßéïng çréätéd. Tö vïéw thé stätüs öf thé " +"répört, séé Péndïng Ìnstrüçtör Täsks ßélöw. Ⱡ'σяєм ιρѕυм #" #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" -"À détäïléd énröllmént 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 єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт" -" łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ " -"єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ " -"αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ " -"ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт#" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." -msgstr "" -"Ýöür éxéçütïvé sümmärý répört ïs ßéïng çréätéd. Tö vïéw thé stätüs öf thé " -"répört, séé thé 'Péndïng Täsks' séçtïön. Ⱡ'σяєм ιρѕυм ∂σł#" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." -msgstr "" -"Àn éxéçütïvé sümmärý répört ïs çürréntlý ïn prögréss. Tö vïéw thé stätüs öf " -"thé répört, séé thé 'Péndïng Täsks' séçtïön. 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. Ýöü wïll ßé äßlé tö döwnlöäd " -"thé répört whén ït ïs çömplété. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя " +"Thé détäïléd énröllmént répört ïs ßéïng çréätéd. Tö vïéw thé stätüs öf thé " +"répört, séé Péndïng Ìnstrüçtör Täsks ßélöw. Ýöü wïll ßé äßlé tö döwnlöäd thé" +" répört whén ït ïs çömplété. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя " "α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα" " αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ " -"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ι#" +"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη " +"яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα " +"ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ι#" + +#: lms/djangoapps/instructor/views/api.py +msgid "" +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." +msgstr "" +"Thé éxéçütïvé sümmärý répört ïs ßéïng çréätéd. Tö vïéw thé stätüs öf thé " +"répört, séé Péndïng Ìnstrüçtör Täsks ßélöw. Ⱡ'σяєм ιρѕυм ∂σ#" + +#: lms/djangoapps/instructor/views/api.py +msgid "" +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." +msgstr "" +"Thé éxéçütïvé sümmärý répört ïs çürréntlý ßéïng çréätéd. Tö vïéw thé stätüs " +"öf thé répört, séé Péndïng Ìnstrüçtör Täsks ßélöw. Ýöü wïll ßé äßlé tö " +"döwnlöäd thé répört whén ït ïs çömplété. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " +"¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт " +"∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση " +"υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє " +"∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα" +" ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂#" #: lms/djangoapps/instructor/views/api.py msgid "Could not parse amount as a decimal" @@ -7031,49 +7110,49 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" -"Ýöür grädé répört ïs ßéïng générätéd! Ýöü çän vïéw thé stätüs öf thé " -"générätïön täsk ïn thé 'Péndïng Täsks' séçtïön. Ⱡ'σяєм ιρѕυм ∂σ#" +"Thé grädé répört ïs ßéïng çréätéd. Tö vïéw thé stätüs öf thé répört, séé " +"Péndïng Ìnstrüçtör Täsks ßélöw. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#" #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" -"À grädé 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 єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт " -"∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση " -"υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє " -"∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα" -" ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ησ#" +"Thé grädé répört ïs çürréntlý ßéïng çréätéd. Tö vïéw thé stätüs öf thé " +"répört, séé Péndïng Ìnstrüçtör Täsks ßélöw. Ýöü wïll ßé äßlé tö döwnlöäd thé" +" répört whén ït ïs çömplété. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя " +"α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα" +" αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ " +"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη " +"яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα " +"ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρ#" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" -"Ýöür prößlém grädé répört ïs ßéïng générätéd! Ýöü çän vïéw thé stätüs öf thé" -" générätïön täsk ïn thé 'Péndïng Täsks' séçtïön. Ⱡ'σяєм ι#" +"Thé prößlém grädé répört ïs ßéïng çréätéd. Tö vïéw thé stätüs öf thé répört," +" séé Péndïng Ìnstrüçtör Täsks ßélöw. Ⱡ'σяєм ιρѕυм ∂σłσя#" #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" -"À prößlém grädé répört ïs älréädý ßéïng générätéd. Ç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 єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт " -"∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση " -"υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє " -"∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα" -" ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσ#" +"À prößlém grädé répört ïs älréädý ßéïng générätéd. Tö vïéw thé stätüs öf thé" +" répört, séé Péndïng Ìnstrüçtör Täsks ßélöw. Ýöü wïll ßé äßlé tö döwnlöäd " +"thé répört whén ït ïs çömplété. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя " +"α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα" +" αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ " +"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη " +"яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα " +"ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт#" #: lms/djangoapps/instructor/views/api.py msgid "Successfully changed due date for student {0} for {1} to {2}" @@ -7249,15 +7328,14 @@ msgid "Data Download" msgstr "Dätä Döwnlöäd Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#" #: lms/djangoapps/instructor/views/instructor_dashboard.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Analytics" -msgstr "Ànälýtïçs Ⱡ'σяєм ιρѕυм ∂σł#" +msgid "For analytics about your course, go to {analytics_dashboard_name}." +msgstr "" +"För änälýtïçs äßöüt ýöür çöürsé, gö tö {analytics_dashboard_name}. Ⱡ'σяєм " +"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя #" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." -msgstr "" -"Démögräphïç dätä ïs nöw äväïläßlé ïn {dashboard_link}. Ⱡ'σяєм ιρѕυм ∂σłσя " -"ѕιт αмєт, ¢σηѕє¢тєтυя #" +msgid "Analytics" +msgstr "Ànälýtïçs Ⱡ'σяєм ιρѕυм ∂σł#" #: lms/djangoapps/instructor/views/instructor_dashboard.py #: lms/templates/courseware/legacy_instructor_dashboard.html @@ -7565,7 +7643,6 @@ msgid "Title" msgstr "Tïtlé Ⱡ'σяєм ιρѕ#" #: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "Ýéär öf Bïrth Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#" @@ -8324,10 +8401,6 @@ msgstr "Çömménts Ⱡ'σяєм ιρѕυм ∂#" msgid "University" msgstr "Ûnïvérsïtý Ⱡ'σяєм ιρѕυм ∂σłσ#" -#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html -msgid "Course" -msgstr "Çöürsé Ⱡ'σяєм ιρѕυ#" - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "Çöürsé Ànnöünçé Däté Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #" @@ -9330,6 +9403,12 @@ msgstr "" msgid "course_id must be provided" msgstr "çöürsé_ïd müst ßé prövïdéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#" +#: lms/djangoapps/teams/views.py +msgid "The supplied topic id {topic_id} is not valid" +msgstr "" +"Thé süpplïéd töpïç ïd {topic_id} ïs nöt välïd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " +"¢σηѕє¢тєтυя#" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "" @@ -9340,17 +9419,17 @@ msgid "last_activity is not yet supported" msgstr "" "läst_äçtïvïtý ïs nöt ýét süppörtéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#" +#: lms/djangoapps/teams/views.py +msgid "The ordering {} is not supported" +msgstr "" +"Thé ördérïng {} ïs nöt süppörtéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#" + #: lms/djangoapps/teams/views.py msgid "The supplied course_id {course_id} is not valid." msgstr "" "Thé süpplïéd çöürsé_ïd {course_id} ïs nöt välïd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт " "αмєт, ¢σηѕє¢тєтυя#" -#: lms/djangoapps/teams/views.py -msgid "The ordering {} is not supported" -msgstr "" -"Thé ördérïng {} ïs nöt süppörtéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#" - #: lms/djangoapps/teams/views.py msgid "username or team_id must be specified." msgstr "" @@ -9419,6 +9498,20 @@ msgstr "" "Théré wäs än érrör vérïfýïng ýöür ÌD phötös. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " "¢σηѕє¢тєтυя #" +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "" +"Thé çöürsé för whïçh thïs déädlïné äpplïés Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " +"¢σηѕє¢тєтυя #" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" +"Thé dätétïmé äftér whïçh üsérs äré nö löngér ällöwéd tö süßmït phötös för " +"vérïfïçätïön. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#" + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "Ìntrö Ⱡ'σяєм ιρѕ#" @@ -10335,6 +10428,10 @@ msgstr "" "À çöhört wïth thé sämé nämé älréädý éxïsts. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " "¢σηѕє¢тєтυя #" +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "Çöürsé Çrédït Élïgïßïlïtý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -10427,6 +10524,37 @@ msgstr "" " νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт " "¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕ#" +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" +"Pläïn téxt ör html çöntént för dïspläýïng çüstöm méssägé ïnsïdé çrédït " +"élïgïßïlïtý émäïl çöntént whïçh ïs sént whén üsér häs mét äll çrédït " +"élïgïßïlïtý réqüïréménts. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя " +"α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα" +" αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ " +"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη " +"яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα " +"ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι " +"σƒƒι¢ια#" + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" +"Pläïn téxt ör html çöntént för dïspläýïng çüstöm méssägé ïnsïdé çrédït " +"réçéïpt émäïl çöntént whïçh ïs sént *äftér* päýïng tö gét çrédït för ä " +"çrédït çöürsé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, " +"ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм " +"α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ " +"єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє" +" νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт " +"¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσ#" + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "" @@ -11145,9 +11273,7 @@ msgstr "Pägé nöt föünd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -11288,6 +11414,11 @@ msgstr "" msgid "Course Navigation" msgstr "Çöürsé Nävïgätïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "Àççöünt Ⱡ'σяєм ιρѕυм #" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py msgid "Help" @@ -11494,7 +11625,8 @@ msgstr "LÉÀRN MÖRÉ Ⱡ'σяєм ιρѕυм ∂σłσ#" msgid "Starts" msgstr "Stärts Ⱡ'σяєм ιρѕυ#" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "Däshßöärd Ⱡ'σяєм ιρѕυм ∂σł#" @@ -11525,16 +11657,12 @@ msgid "Clear search" msgstr "Çléär séärçh Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" -msgstr "" -"Wänt tö çhängé ýöür äççöünt séttïngs? Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " -"¢σηѕє¢тєтυ#" +msgid "Find New Courses" +msgstr "Fïnd Néw Çöürsés Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." -msgstr "" -"Çlïçk thé ärröw néxt tö ýöür üsérnämé äßövé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " -"¢σηѕє¢тєтυя #" +msgid "Account Status Info" +msgstr "Àççöünt Stätüs Ìnfö Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт,#" #: lms/templates/dashboard.html msgid "Order History" @@ -12238,27 +12366,23 @@ msgid "More options dropdown" msgstr "Möré öptïöns dröpdöwn Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "Àççöünt Séttïngs Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" -msgstr "Mý Pröfïlé Ⱡ'σяєм ιρѕυм ∂σłσ#" +msgid "Profile" +msgstr "Pröfïlé Ⱡ'σяєм ιρѕυм #" #: lms/templates/navigation-edx.html lms/templates/navigation.html #: lms/templates/shoppingcart/shopping_cart.html msgid "Shopping Cart" msgstr "Shöppïng Çärt Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" -msgstr "Régïstér Ⱡ'σяєм ιρѕυм ∂#" - #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "Sign in" msgstr "Sïgn ïn Ⱡ'σяєм ιρѕυм #" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +#: lms/templates/register.html +msgid "Register" +msgstr "Régïstér Ⱡ'σяєм ιρѕυм ∂#" + #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "" "Warning: Your browser is not fully supported. We strongly " @@ -12281,10 +12405,6 @@ msgstr "Sýsädmïn Ⱡ'σяєм ιρѕυм ∂#" msgid "Schools" msgstr "Sçhööls Ⱡ'σяєм ιρѕυм #" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "Régïstér Nöw Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -13458,6 +13578,13 @@ msgstr "" "Ì çömplétéd thé {course_title} çöürsé ön {platform_name}. Ⱡ'σяєм ιρѕυм ∂σłσя" " ѕιт αмєт, ¢σηѕє¢тєт#" +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" +"Ì çömplétéd ä çöürsé ön {platform_name}. Täké ä löök ät mý çértïfïçäté. " +"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "" @@ -13468,6 +13595,17 @@ msgstr "" msgid "Post on Facebook" msgstr "Pöst ön Fäçéßöök Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "Shäré ön Twïttér Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "" +"Twéét thïs Àççömplïshmént. Pöp üp wïndöw. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " +"¢σηѕє¢тєтυя #" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "Àdd tö LïnkédÌn Pröfïlé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#" @@ -13738,6 +13876,10 @@ msgstr "{chapter}, çürrént çhäptér Ⱡ'σяєм ιρѕυм ∂σłσя ѕ msgid "due {date}" msgstr "düé {date} Ⱡ'σяєм ιρѕυм #" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "Thïs séçtïön ïs grädéd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#" + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -13864,10 +14006,6 @@ msgstr "Çlässés Énd Ⱡ'σяєм ιρѕυм ∂σłσя #" msgid "Estimated Effort" msgstr "Éstïmätéd Éffört Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "Prïçé Ⱡ'σяєм ιρѕ#" - #: lms/templates/courseware/course_about.html msgid "Prerequisites" msgstr "Préréqüïsïtés Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#" @@ -13898,13 +14036,27 @@ msgstr "Çöürsé Vïéw Ⱡ'σяєм ιρѕυм ∂σłσя #" msgid "View this course as:" msgstr "Vïéw thïs çöürsé äs: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "Spéçïfïç stüdént Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "Stüdént ïn {content_group} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" -msgstr "sét prévïéw mödé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" +msgid "Username or email:" +msgstr "Ûsérnämé ör émäïl: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" +msgstr "Sét prévïéw mödé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" + +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." +msgstr "" +"Ýöü äré nöw vïéwïng thé çöürsé äs {user_name}. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт" +" αмєт, ¢σηѕє¢тєтυя #" #: lms/templates/courseware/course_navigation.html msgid "Course Material" @@ -13945,6 +14097,10 @@ msgstr "" msgid "{platform_name} Logo" msgstr "{platform_name} Lögö Ⱡ'σяєм ιρѕυм ∂#" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "Lïst öf Çöürsés Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "Réfïné ýöür séärçh Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#" @@ -14303,86 +14459,6 @@ msgstr "" "Tö sénd émäïl, vïsït thé Émäïl séçtïön öf thé Ìnstrüçtör Däshßöärd. Ⱡ'σяєм " "ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя #" -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "" -"Nö Ànälýtïçs äré äväïläßlé ät thïs tïmé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " -"¢σηѕє¢тєтυя#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "Stüdént äçtïvïtý däý ßý däý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "Däý Ⱡ'σяєм#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "Stüdénts Ⱡ'σяєм ιρѕυм ∂#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "Sçöré dïstrïßütïön för prößléms Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "Mäx Ⱡ'σяєм#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "Pöïnts Éärnéd (Nüm Stüdénts) Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "" -"Théré ïs nö dätä äväïläßlé tö dïspläý ät thïs tïmé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт " -"αмєт, ¢σηѕє¢тєтυя α#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "" -"Löädïng thé lätést gräphs för ýöü; dépéndïng ön ýöür çläss sïzé, thïs mäý " -"täké ä féw mïnütés. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "" -"Çöünt öf Stüdénts thät Öpénéd ä Süßséçtïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " -"¢σηѕє¢тєтυя #" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr "Grädé Dïstrïßütïön pér Prößlém Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "" -"Théré äré nö prößléms ïn thïs séçtïön. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " -"¢σηѕє¢тєтυя#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "Stüdénts änswérïng çörréçtlý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "Nümßér öf stüdénts Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" -"Stüdént dïstrïßütïön pér çöüntrý, äll çöürsés, Sép 12 tö Öçt 17, 1 sérvér " -"(shöwn héré äs än éxämplé): Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#" - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "Péndïng Ìnstrüçtör Täsks Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢ση#" @@ -14571,16 +14647,17 @@ msgid "Requirements for Course Credit" msgstr "Réqüïréménts för Çöürsé Çrédït Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." +msgid "{student_name}, you are no longer eligible for credit in this course." msgstr "" -"Ýöü äré nö löngér élïgïßlé för thïs çöürsé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " -"¢σηѕє¢тєтυя #" +"{student_name}, ýöü äré nö löngér élïgïßlé för çrédït ïn thïs çöürsé. Ⱡ'σяєм" +" ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#" #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." +msgid "" +"{student_name}, you have met the requirements for credit in this course." msgstr "" -"Ýöü hävé mét thé réqüïréménts för çrédït ïn thïs çöürsé. Ⱡ'σяєм ιρѕυм ∂σłσя " -"ѕιт αмєт, ¢σηѕє¢тєтυя α#" +"{student_name}, ýöü hävé mét thé réqüïréménts för çrédït ïn thïs çöürsé. " +"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#" #: lms/templates/courseware/progress.html msgid "{link} to purchase course credit." @@ -14655,6 +14732,68 @@ msgstr "" "Ýöü wéré möst réçéntlý ïn {section_link}. Ìf ýöü'ré döné wïth thät, çhöösé " "änöthér séçtïön ön thé léft. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#" +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "Hï {name}, Ⱡ'σяєм ιρѕυм #" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" +"Çöngrätülätïöns! Ýöü äré élïgïßlé tö réçéïvé ünïvérsïtý çrédït fröm édX " +"pärtnérs! Çlïçk {link} tö gét ýöür çrédït nöw. Ⱡ'σяєм ιρѕυм ∂σł#" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" +"Çrédït fröm çän hélp ýöü gét ä jümp stärt ön ýöür ünïvérsïtý dégréé, fïnïsh " +"ä dégréé älréädý stärtéd, ör fülfïll réqüïréménts ät ä dïfférént äçädémïç " +"ïnstïtütïön. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ " +"∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ " +"мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ " +"єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє " +"νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт " +"¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕ#" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" +"Tö gét ünïvérsïtý çrédït för {course_name}, sïmplý gö tö ýöür {link} änd " +"çlïçk thé ýéllöw \"Gét Çrédït\" ßüttön. Nö äpplïçätïön, tränsçrïpt, ör grädé" +" répört ïs réqüïréd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg " +"єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт " +"єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт " +"αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη " +"νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт " +"σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłł#" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" +"Wé höpé ýöü énjöýéd thé çöürsé, änd wé höpé tö séé ýöü ïn fütüré édX " +"çöürsés! Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "Thé édX téäm Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "" +"Fïnd möré édX çöürsés ýöü çän täké för ünïvérsïtý çrédït. Ⱡ'σяєм ιρѕυм ∂σłσя" +" ѕιт αмєт, ¢σηѕє¢тєтυя α#" + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -14808,10 +14947,6 @@ msgstr "Shäré ön Fäçéßöök Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α msgid "I'm learning on {platform_name}:" msgstr "Ì'm léärnïng ön {platform_name}: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "Shäré ön Twïttér Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "Çöürsé öptïöns dröpdöwn Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#" @@ -15890,11 +16025,6 @@ msgstr "" "Ýöü hävé ßéén ïnvïtéd tö ä ßétä tést för {course_name} Ⱡ'σяєм ιρѕυм ∂σłσя " "ѕιт αмєт, ¢σηѕє¢тєтυя #" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "Hï {name}, Ⱡ'σяєм ιρѕυм #" - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "Thänk ýöü för ýöür pürçhäsé öf Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#" @@ -17753,34 +17883,6 @@ msgstr "" msgid "Send me a copy of the invoice" msgstr "Sénd mé ä çöpý öf thé ïnvöïçé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "Sçöré Dïstrïßütïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "" -"Thé çhärt ßélöw dïspläýs thé sçöré dïstrïßütïön för éäçh ständärd prößlém ïn" -" ýöür çläss, spéçïfïéd ßý thé prößlém's ürl nämé. Ⱡ'σяєм #" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "" -"Sçörés äré shöwn wïthöüt wéïghtïng äpplïéd, sö ïf ýöür prößlém çöntäïns 2 " -"qüéstïöns, ït wïll dïspläý äs hävïng ä tötäl öf 2 pöïnts. Ⱡ#" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "Löädïng prößlém lïst... Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "Géndér Dïstrïßütïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт,#" - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "Ìnstrüçtör Däshßöärd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #" @@ -18076,6 +18178,12 @@ msgstr "" msgid "Add CCX Coach" msgstr "Àdd ÇÇX Çöäçh Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "" +"Théré ïs nö dätä äväïläßlé tö dïspläý ät thïs tïmé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт " +"αмєт, ¢σηѕє¢тєтυя α#" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "" @@ -18140,6 +18248,10 @@ msgstr "" "Döwnlöäd Prößlém Dätä för äll Prößléms äs ä ÇSV Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт," " ¢σηѕє¢тєтυя α#" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr "Grädé Dïstrïßütïön pér Prößlém Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "" @@ -18156,6 +18268,12 @@ msgstr "" "Thïs ïs ä pärtïäl lïst, tö vïéw äll stüdénts döwnlöäd äs ä çsv. Ⱡ'σяєм ιρѕυм" " ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "" +"Théré äré nö prößléms ïn thïs séçtïön. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " +"¢σηѕє¢тєтυя#" + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "Sénd Émäïl Ⱡ'σяєм ιρѕυм ∂σłσ#" @@ -19108,6 +19226,10 @@ msgstr "Prïçé pér stüdént: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм msgid "Discount Applied:" msgstr "Dïsçöünt Àpplïéd: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "Stüdénts Ⱡ'σяєм ιρѕυм ∂#" + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -19419,6 +19541,10 @@ msgstr "" "Çürréntlý thé {platform_name} sérvérs äré övérlöädéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт " "αмєт, ¢σηѕє¢тєтυя#" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "Àççöünt Séttïngs Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "Pléäsé Wäït Ⱡ'σяєм ιρѕυм ∂σłσя #" @@ -19549,18 +19675,30 @@ msgstr "" msgid "Re-Verify for {course_name}" msgstr "Ré-Vérïfý för {course_name} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "" "Vérïfïçätïön Déädlïné Häs Pässéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "Ûpgrädé Déädlïné Häs Pässéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." msgstr "" -"Thé vérïfïçätïön déädlïné för {course_name} wäs {date}. Vérïfïçätïön ïs nö " -"löngér äväïläßlé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#" +"Thé vérïfïçätïön déädlïné för {course_name} wäs {date}. Vérïfïçätïön ïs nö " +"löngér äväïläßlé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#" + +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" +"Thé déädlïné tö üpgrädé tö ä vérïfïéd çértïfïçäté för thïs çöürsé häs " +"pässéd. Ýöü çän stïll éärn än hönör çödé çértïfïçäté. Ⱡ'σяєм ιρ#" #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." @@ -23601,10 +23739,6 @@ msgstr "Éxpört Ⱡ'σяєм ιρѕυ#" msgid "Current Library:" msgstr "Çürrént Lïßrärý: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "Àççöünt Ⱡ'σяєм ιρѕυм #" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "Àççöünt Nävïgätïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#" diff --git a/conf/locale/eo/LC_MESSAGES/djangojs.mo b/conf/locale/eo/LC_MESSAGES/djangojs.mo index 9e7cdbaa95..9910f967ce 100644 Binary files a/conf/locale/eo/LC_MESSAGES/djangojs.mo and b/conf/locale/eo/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/eo/LC_MESSAGES/djangojs.po b/conf/locale/eo/LC_MESSAGES/djangojs.po index 797f2e0907..270ea57afb 100644 --- a/conf/locale/eo/LC_MESSAGES/djangojs.po +++ b/conf/locale/eo/LC_MESSAGES/djangojs.po @@ -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-07-13 04:40+0000\n" -"PO-Revision-Date: 2015-07-13 04:42:08.623413\n" +"POT-Creation-Date: 2015-07-22 18:11+0000\n" +"PO-Revision-Date: 2015-07-22 18:12:54.993319\n" "Last-Translator: \n" "Language-Team: openedx-translation \n" "MIME-Version: 1.0\n" @@ -2392,28 +2392,50 @@ msgstr "Réplý Ⱡ'σяєм ιρѕ#" msgid "Tags:" msgstr "Tägs: Ⱡ'σяєм ιρѕ#" +#: 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" msgstr "nämé Ⱡ'σяєм ι#" +#: 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 msgid "team count" msgstr "téäm çöünt Ⱡ'σяєм ιρѕυм ∂σłσ#" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "" +"%(member_count)s / %(max_member_count)s Mémßér Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" +msgstr[1] "" +"%(member_count)s / %(max_member_count)s Mémßérs Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#" + +#: 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/teams.js +msgid "Create new team" +msgstr "Çréäté néw téäm Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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 "" -"Çöürsé téäms äré örgänïzéd ïntö töpïçs çréätéd ßý çöürsé ïnstrüçtörs. Trý tö" -" jöïn öthérs ïn än éxïstïng téäm ßéföré ýöü déçïdé tö çréäté ä néw téäm! " -"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ " -"тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм," -" qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ " +"Séé äll téäms ïn ýöür çöürsé, örgänïzéd ßý töpïç. Jöïn ä téäm tö çölläßöräté" +" wïth öthér léärnérs whö äré ïntéréstéd ïn thé sämé töpïç äs ýöü äré. Ⱡ'σяєм" +" ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя " +"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ " +"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ " "¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє " "¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт " -"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм#" +"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂#" #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "Teams" @@ -2427,6 +2449,18 @@ msgstr "Mý Téäms Ⱡ'σяєм ιρѕυм ∂#" msgid "Browse" msgstr "Bröwsé Ⱡ'σяєм ιρѕυ#" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "" +"Thé pägé \"%(route)s\" çöüld nöt ßé föünd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " +"¢σηѕє¢тєт#" + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "" +"Thé töpïç \"%(topic)s\" çöüld nöt ßé föünd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " +"¢σηѕє¢тєт#" + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2490,23 +2524,6 @@ msgstr "" "Érrör générätïng prößlém grädé répört. Pléäsé trý ägäïn. Ⱡ'σяєм ιρѕυм ∂σłσя " "ѕιт αмєт, ¢σηѕє¢тєтυя α#" -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "Ûnäväïläßlé métrïç dïspläý. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "" -"Érrör fétçhïng grädé dïstrïßütïöns. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "Läst Ûpdätéd: <%= timestamp %> Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "<%= num_students %> stüdénts sçöréd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #" - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3481,6 +3498,12 @@ msgstr "" "Àn érrör öççürréd. Pléäsé trý ägäïn lätér. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " "¢σηѕє¢тєтυя #" +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "Vïéwïng %s çöürsé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#" +msgstr[1] "Vïéwïng %s çöürsés Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "" @@ -3498,8 +3521,8 @@ msgstr "" msgid "Focus grabber" msgstr "Föçüs gräßßér Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." @@ -3507,6 +3530,22 @@ msgstr "" "Àn érrör häs öççürréd. Mäké süré thät ýöü äré çönnéçtéd tö thé Ìntérnét, änd" " thén trý réfréshïng thé pägé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт #" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "Hïdé nötés Ⱡ'σяєм ιρѕυм ∂σłσ#" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "Nötés vïsïßlé Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "Shöw nötés Ⱡ'σяєм ιρѕυм ∂σłσ#" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "Nötés hïddén Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3518,22 +3557,6 @@ msgstr "" msgid "Current tab" msgstr "Çürrént täß Ⱡ'σяєм ιρѕυм ∂σłσя #" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "Hïdé nötés Ⱡ'σяєм ιρѕυм ∂σłσ#" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "Nötés vïsïßlé Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "Shöw nötés Ⱡ'σяєм ιρѕυм ∂σłσ#" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "Nötés hïddén Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "Löçätïön ïn Çöürsé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#" @@ -5654,6 +5677,24 @@ msgstr "rémövé äll Ⱡ'σяєм ιρѕυм ∂σłσ#" msgid "remove" msgstr "rémövé Ⱡ'σяєм ιρѕυ#" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "géttéxt( Ⱡ'σяєм ιρѕυм ∂#" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "%s Ⱡ'σяєм ιρѕυ#" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" +" Ⱡ'σяєм " +"ιρѕυм ∂#" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "" @@ -5763,10 +5804,6 @@ msgstr "LÉSS... Ⱡ'σяєм ιρѕυм #" msgid "LEARN MORE" msgstr "LÉÀRN MÖRÉ Ⱡ'σяєм ιρѕυм ∂σłσ#" -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "géttéxt( Ⱡ'σяєм ιρѕυм ∂#" - #: lms/templates/discovery/result_item.underscore msgid "Starts" msgstr "Stärts Ⱡ'σяєм ιρѕυ#" @@ -6886,12 +6923,6 @@ msgstr "stätüs Ⱡ'σяєм ιρѕυ#" msgid "Common Problem Types" msgstr "Çömmön Prößlém Týpés Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "" -"Çömmön Prößléms wïth Hïnts änd Féédßäçk Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " -"¢σηѕє¢тєтυя#" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "Àdd Néw Çömpönént Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#" diff --git a/conf/locale/es_419/LC_MESSAGES/django.mo b/conf/locale/es_419/LC_MESSAGES/django.mo index cfd165cd06..a711426a64 100644 Binary files a/conf/locale/es_419/LC_MESSAGES/django.mo and b/conf/locale/es_419/LC_MESSAGES/django.mo differ diff --git a/conf/locale/es_419/LC_MESSAGES/django.po b/conf/locale/es_419/LC_MESSAGES/django.po index 3af68e91cc..7b4605acda 100644 --- a/conf/locale/es_419/LC_MESSAGES/django.po +++ b/conf/locale/es_419/LC_MESSAGES/django.po @@ -30,10 +30,12 @@ # Natalia, 2013 # Natalia, 2013-2014 # Nuri Plans Toral , 2015 +# Patricia Colmenares , 2015 # rcelaya , 2014 # Sarina Canelake , 2014-2015 # Sergio A. Salazar , 2015 # sebasco , 2014 +# UAbierta Universidad de Chile , 2015 # xocoyotzin, 2014 # Valeria Freire , 2014-2015 # wjmendez , 2014 @@ -146,8 +148,10 @@ # Natalia, 2013 # Nuri Plans Toral , 2015 # Cristian Salamea , 2013 +# Patricia Colmenares , 2015 # paul ochoa , 2015 # Sarina Canelake , 2014 +# UAbierta Universidad de Chile , 2015 # Valeria Freire , 2015 # #-#-#-#-# messages.po (edx-platform) #-#-#-#-# # edX translation file @@ -168,10 +172,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:33+0000\n" +"POT-Creation-Date: 2015-07-22 17:45+0000\n" "PO-Revision-Date: 2015-06-29 17:10+0000\n" "Last-Translator: Cristian Salamea \n" -"Language-Team: Spanish (Latin America) (http://www.transifex.com/p/edx-platform/language/es_419/)\n" +"Language-Team: Spanish (Latin America) (http://www.transifex.com/projects/p/edx-platform/language/es_419/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -193,8 +197,6 @@ msgstr "Discusión" #: cms/djangoapps/contentstore/views/component.py #: lms/djangoapps/class_dashboard/dashboard_data.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Problem" msgstr "Problema" @@ -299,6 +301,68 @@ msgstr "" "cruzado a este sitio. Por favor ingrese cada dominio en una línea " "independiente." +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "Modo" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html +msgid "Course" +msgstr "Curso" + +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/annotatable_module.py +#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/combined_open_ended_module.py +#: common/lib/xmodule/xmodule/discussion_module.py +#: common/lib/xmodule/xmodule/html_module.py +#: common/lib/xmodule/xmodule/imageannotation_module.py +#: common/lib/xmodule/xmodule/library_content_module.py +#: common/lib/xmodule/xmodule/lti_module.py +#: common/lib/xmodule/xmodule/peer_grading_module.py +#: common/lib/xmodule/xmodule/split_test_module.py +#: common/lib/xmodule/xmodule/textannotation_module.py +#: common/lib/xmodule/xmodule/videoannotation_module.py +#: common/lib/xmodule/xmodule/word_cloud_module.py +#: cms/templates/container.html cms/templates/library.html +msgid "Display Name" +msgstr "Nombre para mostrar:" + +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "Precio" + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "Certificado de Código de Honor" @@ -686,11 +750,9 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" -"Si todavía no tiene una cuenta de {platform_name}, haga clic en " -"Regístrese ahora en la parte superior de la página." #: common/djangoapps/student/views.py msgid "There was an error receiving your login information. Please email us." @@ -1723,23 +1785,6 @@ msgstr "No fue posible interpretar '{given_answer}' como un número." msgid "XML data for the annotation" msgstr "Datos XML para la anotación" -#: common/lib/xmodule/xmodule/annotatable_module.py -#: common/lib/xmodule/xmodule/capa_base.py -#: common/lib/xmodule/xmodule/combined_open_ended_module.py -#: common/lib/xmodule/xmodule/discussion_module.py -#: common/lib/xmodule/xmodule/html_module.py -#: common/lib/xmodule/xmodule/imageannotation_module.py -#: common/lib/xmodule/xmodule/library_content_module.py -#: common/lib/xmodule/xmodule/lti_module.py -#: common/lib/xmodule/xmodule/peer_grading_module.py -#: common/lib/xmodule/xmodule/split_test_module.py -#: common/lib/xmodule/xmodule/textannotation_module.py -#: common/lib/xmodule/xmodule/videoannotation_module.py -#: common/lib/xmodule/xmodule/word_cloud_module.py -#: cms/templates/container.html cms/templates/library.html -msgid "Display Name" -msgstr "Nombre para mostrar:" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1869,14 +1914,9 @@ msgstr "Aleatorización de problemas:" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" -"Define con qué frecuencia se aleatorizadas las entradas cuando un estudiante" -" carga el problema. Este ajuste sólo se aplica a los problemas que pueden " -"generar aleatoriamente valores numéricos. Un valor predeterminado puede " -"establecerse en Configuración avanzada." #: common/lib/xmodule/xmodule/capa_base.py msgid "On Reset" @@ -3497,10 +3537,6 @@ msgstr "Seleccione la librería desde la que quieres dibujar el contenido." msgid "Library Version" msgstr "Versión de Libería" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "Modo" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "Determina como se obtiene el contenido de la librería" @@ -4177,15 +4213,12 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" -"Definir con que frecuencia de deben aleatorizar los valores variables del " -"problema. Los valores válidos son: \"always\", \"onreset\", \"never\", y " -"\"per_student\". Esta configuración solo aplica para los problemas que " -"tienen valores numéricos generados aleatoriamente. " #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "Days Early for Beta Users" @@ -4994,7 +5027,7 @@ msgstr "Políticas de Accesibilidad" #: lms/djangoapps/branding/api.py openedx/core/djangoapps/user_api/views.py #: cms/templates/widgets/footer.html lms/templates/static_templates/tos.html msgid "Terms of Service" -msgstr "Términos de Servicio" +msgstr "Términos del servicio" #: lms/djangoapps/branding/api.py msgid "Download the {platform_name} mobile app from the Apple App Store" @@ -5363,11 +5396,11 @@ msgstr "Certificados de validación" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" -msgstr "nombre de usuario" +msgstr "Nombre de usuario" #: lms/djangoapps/class_dashboard/dashboard_data.py #: lms/templates/instructor/instructor_dashboard_2/metrics.html @@ -5485,6 +5518,34 @@ msgstr "Bienvenido a la Wiki {platform_name}" msgid "Visit a course wiki to add an article." msgstr "Visite la wiki de un curso para añadir un artículo." +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" + #: lms/djangoapps/courseware/tabs.py #: lms/templates/courseware/courseware-error.html msgid "Courseware" @@ -5769,7 +5830,7 @@ msgstr "Cursos cargados en la bodega de módulos" #: lms/djangoapps/dashboard/sysadmin.py lms/templates/tracking_log.html msgid "username" -msgstr "Nombre de usuario" +msgstr "nombre de usuario" #: lms/djangoapps/dashboard/sysadmin.py msgid "email" @@ -6154,7 +6215,6 @@ msgstr "Género" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/tasks_helper.py -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Level of Education" msgstr "Nivel educativo" @@ -6174,28 +6234,22 @@ msgstr "Cohorte" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -6258,29 +6312,28 @@ msgstr "Cantidad Total descontada" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -6338,28 +6391,28 @@ msgstr "No se puede repuntuar con all_students y unique_student_identifier." #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -6500,13 +6553,12 @@ msgid "Data Download" msgstr "Descarga de Datos" #: lms/djangoapps/instructor/views/instructor_dashboard.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Analytics" -msgstr "Analíticas" +msgid "For analytics about your course, go to {analytics_dashboard_name}." +msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." -msgstr "Los datos demográficos están disponibles en {dashboard_link}." +msgid "Analytics" +msgstr "Analíticas" #: lms/djangoapps/instructor/views/instructor_dashboard.py #: lms/templates/courseware/legacy_instructor_dashboard.html @@ -6792,7 +6844,6 @@ msgid "Title" msgstr "Título" #: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "Año de nacimiento" @@ -7482,10 +7533,6 @@ msgstr "Comentarios" msgid "University" msgstr "Universidad" -#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html -msgid "Course" -msgstr "Curso" - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "Fecha de anuncio del curso" @@ -8399,6 +8446,10 @@ msgstr "El ID de curso proporcionado {course_id} no es válido." 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 "" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "text_search actualmente no está soportado" @@ -8407,14 +8458,14 @@ msgstr "text_search actualmente no está soportado" msgid "last_activity is not yet supported" msgstr "last_activity actualmente no está soportado." -#: lms/djangoapps/teams/views.py -msgid "The supplied course_id {course_id} is not valid." -msgstr "El ID de curso proporcionado {course_id} no es válido." - #: lms/djangoapps/teams/views.py msgid "The ordering {} is not supported" msgstr "El orden {} no está soportado" +#: lms/djangoapps/teams/views.py +msgid "The supplied course_id {course_id} is not valid." +msgstr "El ID de curso proporcionado {course_id} no es válido." + #: lms/djangoapps/teams/views.py msgid "username or team_id must be specified." msgstr "Debe especificarse el nombre de usuario o el ID del equipo." @@ -8470,6 +8521,16 @@ msgstr "Su rostro no fue visible un tu foto de carnet." msgid "There was an error verifying your ID photos." msgstr "Hubo un error verificando las fotos de su documento de identidad." +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "Introducción" @@ -8818,7 +8879,7 @@ msgstr "Cambiar Mi Contraseña" #: lms/templates/registration/password_reset_confirm.html msgid "Your Password Reset Was Unsuccessful" -msgstr "El Restablecimiento de Contraseña No Tuvo Éxito" +msgstr "El restablecimiento de contraseña no tuvo éxito" #: lms/templates/registration/password_reset_confirm.html msgid "" @@ -9324,6 +9385,10 @@ msgstr "" msgid "A cohort with the same name already exists." msgstr "Ya existe una cohorte con ese nombre." +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -9382,6 +9447,20 @@ msgid "" "credit provider." msgstr "" +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "" @@ -10033,9 +10112,7 @@ msgstr "No se encontró la página" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -10118,7 +10195,7 @@ msgstr "Ejemplo: Juliana Sánchez" #: cms/templates/register.html lms/templates/register-shib.html #: lms/templates/register.html lms/templates/signup_modal.html msgid "Public Username" -msgstr "Nombre de usuario público" +msgstr "Nombre público de usuario " #. Translators: This is the placeholder text for a field that asks the user to #. pick a username @@ -10160,7 +10237,7 @@ msgstr "Gracias por activar su cuenta." #: cms/templates/registration/activation_complete.html #: lms/templates/registration/activation_complete.html msgid "This account has already been activated." -msgstr "Está cuenta ya ha sido activada." +msgstr "La cuenta ya ha sido activada." #: cms/templates/registration/activation_complete.html #: lms/templates/registration/activation_complete.html @@ -10171,6 +10248,11 @@ msgstr "Visite su {link_start}Panel de control{link_end} para ver sus cursos." msgid "Course Navigation" msgstr "Navegación del curso" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py msgid "Help" @@ -10350,13 +10432,14 @@ msgstr "Esconder anotaciones" #: lms/templates/course.html msgid "LEARN MORE" -msgstr "APRENDER MAS" +msgstr "Aprender más" #: lms/templates/course.html msgid "Starts" msgstr "Empieza" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "Panel de control" @@ -10385,12 +10468,12 @@ msgid "Clear search" msgstr "Reiniciar búsqueda" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" -msgstr "¿Desea cambiar su configuración de cuenta?" +msgid "Find New Courses" +msgstr "" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." -msgstr "Haga clic en la flecha sobre su nombre de usuario." +msgid "Account Status Info" +msgstr "" #: lms/templates/dashboard.html msgid "Order History" @@ -10549,8 +10632,8 @@ msgstr "Su dirección de correo electrónico" #: lms/templates/forgot_password_modal.html lms/templates/login.html msgid "This is the e-mail address you used to register with {platform}" msgstr "" -"Esta es la dirección de correo electrónico que uso para registrarse con " -"{platform}" +"Esta es la dirección de correo electrónico que usó para registrarse con " +"{platform} " #: lms/templates/forgot_password_modal.html msgid "Reset My Password" @@ -10753,7 +10836,7 @@ msgstr "Clave de cambio de correo electrónico inválida" #: lms/templates/invalid_email_key.html msgid "This e-mail key is not valid. Please check:" -msgstr "Esta clave de correo electrónica no es valida. Por favor revisar:" +msgstr "Esta clave de correo electrónica no es válida. Por favor revisar:" #: lms/templates/invalid_email_key.html msgid "" @@ -11020,27 +11103,23 @@ msgid "More options dropdown" msgstr "Despliegue de más opciones" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "Configuración de la cuenta" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" -msgstr "Mi Perfil" +msgid "Profile" +msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html #: lms/templates/shoppingcart/shopping_cart.html msgid "Shopping Cart" msgstr "Carro de compras" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" -msgstr "Registrarse" - #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "Sign in" msgstr "Iniciar sesión" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +#: lms/templates/register.html +msgid "Register" +msgstr "Registrarse" + #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "" "Warning: Your browser is not fully supported. We strongly " @@ -11062,10 +11141,6 @@ msgstr "Sysadmin" msgid "Schools" msgstr "Instituciones" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "Registrarse" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -11208,11 +11283,8 @@ msgid "" "mark emails from class.stanford.edu as 'not spam', since you'll want to be " "able to receive email from your courses." msgstr "" -"Usted recibirá un correo electrónico de activación. Debe hacer clic en el " -"enlace de activación para completar el proceso. ¿No ve el correo " -"electrónico? Revise su carpeta de spam y marque los correos electrónicos " -"provenientes de class.stanford.edu como \"no es spam\", ya que usted querrá " -"ser capaz de recibir correos electrónicos de sus cursos." +"Usted recibirá un correo electrónico de activación. Debe hacer clic en el enlace de activación para completar el proceso. ¿No ve el correo electrónico? Revise su carpeta de spam. \n" +"Aconsejamos marcar nuestros correos electrónicos como \"no es spam\", así podrá recibirlos siempre en la bandeja de entrada. " #: lms/templates/register-sidebar.html msgid "" @@ -11261,7 +11333,7 @@ msgstr "Bienvenido!" #: lms/templates/register.html msgid "Register below to create your {platform_name} account" -msgstr "Regístrese a continuación para crear su cuenta en {platform_name}" +msgstr "Regístrese para crear su cuenta en {platform_name}" #. Translators: provider_name is the name of an external, third-party user #. authentication service (like Google or LinkedIn). @@ -11284,8 +11356,8 @@ msgid "" "We just need a little more information before you start learning with " "{platform_name}." msgstr "" -"Solo necesitamos un poco más de información antes de que comience a aprender" -" con {platform_name}." +"Necesitamos un poco más de información antes de que comience a aprender con " +"{platform_name}." #: lms/templates/register.html msgid "Please complete the following fields to register for an account. " @@ -11297,7 +11369,7 @@ msgstr "No podrá ser cambiada después" #: lms/templates/register.html msgid "Welcome {username}" -msgstr "Bienvenido(a) {username}" +msgstr "Bienvenid@ {username}" #: lms/templates/register.html msgid "Enter a Public Display Name:" @@ -11846,7 +11918,7 @@ msgstr "Ejemplos" #: lms/templates/calculator/toggle_calculator.html msgid "Numbers" -msgstr "Numeros" +msgstr "Números" #: lms/templates/calculator/toggle_calculator.html msgid "Integers" @@ -12146,6 +12218,11 @@ msgstr "" msgid "I completed the {course_title} course on {platform_name}." msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "" @@ -12154,6 +12231,15 @@ msgstr "" msgid "Post on Facebook" msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "Compartir en Twitter" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "Agregar al Perfil de LinkedIn" @@ -12303,7 +12389,7 @@ msgstr "Responder a los comentarios" #: lms/templates/combinedopenended/open_ended_result_table.html #: lms/templates/combinedopenended/openended/open_ended_evaluation.html msgid "How accurate do you find this feedback?" -msgstr "¿Que tan realista le parece este comentario?" +msgstr "¿Que tan preciso y justo le parece este comentario?" #: lms/templates/combinedopenended/open_ended_result_table.html #: lms/templates/combinedopenended/openended/open_ended_evaluation.html @@ -12313,7 +12399,7 @@ msgstr "Parcialmente correcto" #: lms/templates/combinedopenended/open_ended_result_table.html #: lms/templates/combinedopenended/openended/open_ended_evaluation.html msgid "No Opinion" -msgstr "No tengo una opinion" +msgstr "No tengo una opinión" #: lms/templates/combinedopenended/open_ended_result_table.html #: lms/templates/combinedopenended/openended/open_ended_evaluation.html @@ -12413,6 +12499,10 @@ msgstr "{chapter}, capítulo actual" msgid "due {date}" msgstr "fecha límite: {date}" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "" + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -12444,7 +12534,7 @@ msgstr "Este curso ya está en su carrito." #: lms/templates/courseware/course_about.html msgid "Course is full" -msgstr "El curso está lleno" +msgstr "El curso copó su capacidad" #: lms/templates/courseware/course_about.html msgid "Enrollment in this course is by invitation only" @@ -12476,7 +12566,7 @@ msgstr "Visión general" #: lms/templates/courseware/course_about.html msgid "Share with friends and family!" -msgstr "Compartir con amigos y familiares!" +msgstr "Compartir con amigos y familiares" #: lms/templates/courseware/course_about.html msgid "Tweet that you've registered for this course" @@ -12491,16 +12581,16 @@ msgstr "Envía un correo a tus amigos que te has registrado en este curso" #: lms/templates/courseware/course_about.html msgid "I just registered for {number} {title} through {account}: {url}" msgstr "" -"Acabo de registrarme para {number} {title} a través de {account}: {url}" +"Acabo de inscribirme para {number} {title} a través de {account}: {url}" #: lms/templates/courseware/course_about.html msgid "Take a course with {platform} online" -msgstr "Tome un curso en línea con {platform} " +msgstr "Tome un curso abierto con {platform} " #: lms/templates/courseware/course_about.html msgid "I just registered for {number} {title} through {platform} {url}" msgstr "" -"Acabo de registrarme para {number} {title} a través de {platform} {url}" +"Acabo de inscribirme para {number} {title} a través de {platform} {url}" #: lms/templates/courseware/course_about.html msgid "Post a Facebook message to say you've registered for this course" @@ -12512,19 +12602,15 @@ msgstr "Inicio de clases" #: lms/templates/courseware/course_about.html msgid "Classes End" -msgstr "Termino de clases" +msgstr "Término de clases" #: lms/templates/courseware/course_about.html msgid "Estimated Effort" msgstr "Esfuerzo estimado" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "Precio" - #: lms/templates/courseware/course_about.html msgid "Prerequisites" -msgstr "Prerequisitos" +msgstr "Prerrequisitos" #: lms/templates/courseware/course_about.html #: lms/templates/dashboard/_dashboard_course_listing.html @@ -12552,13 +12638,25 @@ msgstr "Ver curso" msgid "View this course as:" msgstr "Ver este curso como:" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "Estudiante en {content_group}" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" -msgstr "activar vista preliminar" +msgid "Username or email:" +msgstr "Nombre de usuario o correo electrónico" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." +msgstr "" #: lms/templates/courseware/course_navigation.html msgid "Course Material" @@ -12594,6 +12692,10 @@ msgstr "Explore cursos de {platform_name}." msgid "{platform_name} Logo" msgstr "Logo de {platform_name}" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "Refinar su búsqueda" @@ -12904,78 +13006,6 @@ msgid "To send email, visit the Email section of the Instructor Dashboard." msgstr "" "Para enviar un email, visita la sección Email en el Panel del Instructor." -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "No hay información de análisis disponible en este momento." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "Actividad de estudiantes día a día" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "Día" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "Estudiantes" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "Distribución de puntajes para los problemas" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "Máx." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "Puntos obtenidos (Núm de Estudiantes)" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "No hay información disponible en este momento." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "" -"Se están cargando los gráficos actualizados. Dependiendo del tamaño de la " -"clase, esto puede tardar algunos minutos." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "Cantidad de estudiantes que abrieron una subsección" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr "Distribución de calificaciones por problema" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "No hay problemas en esta sección." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "Estudiantes que respondieron correctamente" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "Número de estudiantes" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" -"Distribución de estudiantes por país para todos los cursos. (Se muestra como" -" ejemplo del 12 de Septiembre al 17 de octubre, 1 servidor)." - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "Tareas de instructor pendientes" @@ -13132,13 +13162,13 @@ msgid "" "We're creating your certificate. You can keep working in your courses and a " "link to it will appear here and on your Dashboard when it is ready." msgstr "" -"Estamos creando su certificado. Puede seguir trabajando en sus cursos y " -"cuando el certificado esté listo, aparecerá un vínculo al mismo en su panel " -"de control. " +"Estamos creando su Constancia de Honor. Puede seguir trabajando en sus " +"cursos y cuando el certificado esté listo, aparecerá un vínculo al mismo en " +"su panel de control. " #: lms/templates/courseware/progress.html msgid "Congratulations, you qualified for a certificate!" -msgstr "Felicitaciones, usted califica para recibir un certificado!" +msgstr "Felicitaciones, usted califica para recibir una Constancia de Honor" #: lms/templates/courseware/progress.html msgid "Request Certificate" @@ -13149,12 +13179,13 @@ msgid "Requirements for Course Credit" msgstr "Requisitos para obtener Crédito del curso" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." -msgstr "Usted ya no es elegible para este curso." +msgid "{student_name}, you are no longer eligible for credit in this course." +msgstr "" #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." -msgstr "Ha completado los requerimientos para obtener crédito por este curso" +msgid "" +"{student_name}, you have met the requirements for credit in this course." +msgstr "" #: lms/templates/courseware/progress.html msgid "{link} to purchase course credit." @@ -13220,6 +13251,46 @@ msgstr "" "Usted visitó recientemente {section_link}. Si ya ha terminado con eso, elija" " otra sección de la izquierda." +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "Hola {name}," + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "" + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -13355,10 +13426,6 @@ msgstr "Compartir en Facebook" msgid "I'm learning on {platform_name}:" msgstr "Estoy aprendiendo en {platform_name}:" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "Compartir en Twitter" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "Despliegue de opciones para el curso" @@ -14321,11 +14388,6 @@ msgstr "" msgid "You have been invited to a beta test for {course_name}" msgstr "Usted ha sido invitado una prueba beta para el curso {course_name}" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "Hola {name}," - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "Gracias por su compra de" @@ -15944,34 +16006,6 @@ msgstr "Orden de compra u otra información de referencia del cliente" msgid "Send me a copy of the invoice" msgstr "Enviarme una copia de la factura" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "Distribución de puntajes" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "" -"El gráfico de abajo muestra la distribución de puntajes para cada problema " -"en su clase, marcadas con la url del problema." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "" -"Se muestran los puntajes sin aplicarles el peso, así que si su problema " -"contiene dos preguntas, se mostrará con un total de 2 puntos." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "Cargando la lista de problemas..." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "Distribución de género" - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "Panel de control del instructor" @@ -16206,6 +16240,10 @@ msgstr "" msgid "Add CCX Coach" msgstr "Añadir tutor CCX" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "No hay información disponible en este momento." + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "Use Recargar gráficos para actualizar la información" @@ -16259,6 +16297,10 @@ msgstr "" msgid "Download Problem Data for all Problems as a CSV" msgstr "Descargar los datos de todos los problemas como CSV" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr "Distribución de calificaciones por problema" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "Descargar la información de estudiantes como archivo CSV" @@ -16273,6 +16315,10 @@ msgstr "" "Esta es una lista parcial. para ver la lista completa, descargue el archivo " "como CSV," +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "No hay problemas en esta sección." + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "Enviar correo electrónico" @@ -17117,6 +17163,10 @@ msgstr "Precio por estudiante:" msgid "Discount Applied:" msgstr "Descuento aplicado:" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "Estudiantes" + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -17387,6 +17437,10 @@ msgstr "" msgid "Currently the {platform_name} servers are overloaded" msgstr "Actualmente los servidores de {platform_name} están sobrecargados" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "Configuración de la cuenta" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "Por favor espere" @@ -17499,17 +17553,25 @@ msgstr "Ocurrió el siguiente error en la edición de su nombre:" msgid "Re-Verify for {course_name}" msgstr "Re-verificando el curso {course_name}" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "La fecha límite de verificación ya pasó" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." msgstr "" -"La fecha límite de verificación para el curso {course_name} era {date}. Este" -" procedimiento ya no está disponible." + +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." @@ -17652,8 +17714,8 @@ msgid "" "This account, set up using {email}, has already been activated. Please sign " "in to start working within {studio_name}." msgstr "" -"Esta cuenta, creada utiliza {email}, ha sido activada. Por favor inicia " -"sesión para empezar a trabajar dentro de {studio_name}." +"La cuenta creada con {email} ha sido activada. Por favor inicia sesión para" +" empezar a trabajar dentro en {studio_name}." #: cms/templates/activation_active.html cms/templates/activation_complete.html msgid "Sign into {studio_name}" @@ -17690,7 +17752,7 @@ msgid "" "If you still have issues, contact {platform_name} Support. In the meantime, " "you can also return to {link_start}the {studio_name} homepage.{link_end}" msgstr "" -"Si udsted aún tienen problemas, contactese con Soporte {platform_name}. " +"Si udsted aún tienen problemas, contáctese con Soporte {platform_name}. " "Mientras tanto, puede volver a {link_start} la página inicial " "{studio_name}. {link_end}" @@ -20690,7 +20752,7 @@ msgstr "Este bloque contiene varios componentes" #: cms/templates/temp-course-landing.html msgid "{platform_name} edge" -msgstr "{platform_name} borde" +msgstr "{platform_name} edge" #: cms/templates/textbooks.html msgid "New Textbook" @@ -20899,15 +20961,16 @@ msgstr "Su cuenta de {studio_name}" #: cms/templates/emails/course_creator_admin_subject.txt msgid "{email} has requested {studio_name} course creator privileges on edge" msgstr "" -"{email} ha solicitado cursos {studio_name} privilegios creador en el borde" +"{email} ha solicitado privilegios de creador de cursos {studio_name} en la " +"plataforma edge" #: cms/templates/emails/course_creator_admin_user_pending.txt msgid "" "User '{user}' with e-mail {email} has requested {studio_name} course creator" " privileges on edge." msgstr "" -"Usuario '{user}' con el e-mail {email} ha solicitado cursos {studio_name} " -"privilegios supuesto del creador de punta." +"Usuario '{user}' con el e-mail {email} ha solicitado privilegios de creador " +"de cursos {studio_name} en la plataforma edge." #: cms/templates/emails/course_creator_admin_user_pending.txt msgid "To grant or deny this request, use the course creator admin table." @@ -21002,10 +21065,6 @@ msgstr "Exportar" msgid "Current Library:" msgstr "Librería actual" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "Cuenta" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "Navegación de cuenta" diff --git a/conf/locale/es_419/LC_MESSAGES/djangojs.mo b/conf/locale/es_419/LC_MESSAGES/djangojs.mo index 49c84cfafa..fe4787bf88 100644 Binary files a/conf/locale/es_419/LC_MESSAGES/djangojs.mo and b/conf/locale/es_419/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/es_419/LC_MESSAGES/djangojs.po b/conf/locale/es_419/LC_MESSAGES/djangojs.po index 8ea11e0833..ed60c70dd1 100644 --- a/conf/locale/es_419/LC_MESSAGES/djangojs.po +++ b/conf/locale/es_419/LC_MESSAGES/djangojs.po @@ -11,6 +11,7 @@ # morsoinferno , 2014-2015 # David Salazar , 2014 # David Salazar , 2014 +# Elias Estay , 2015 # Felipe Schmidt M , 2015 # Fernando Abramowitz , 2014 # Gerardo Laster, 2014 @@ -69,6 +70,7 @@ # Juan Fernando Villa , 2015 # Juan , 2015 # Nuri Plans Toral , 2014 +# Patricia Colmenares , 2015 # paul ochoa , 2015 # Thomas Alberto Castro Acosta , 2014 # Valeria Freire , 2014-2015 @@ -85,14 +87,15 @@ # Juan Camilo Montoya Franco , 2014 # Juan , 2015 # karlman72 , 2014 +# Patricia Colmenares , 2015 msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:31+0000\n" -"PO-Revision-Date: 2015-07-10 19:12+0000\n" -"Last-Translator: Sarina Canelake \n" -"Language-Team: Spanish (Latin America) (http://www.transifex.com/p/edx-platform/language/es_419/)\n" +"POT-Creation-Date: 2015-07-22 17:43+0000\n" +"PO-Revision-Date: 2015-07-20 21:04+0000\n" +"Last-Translator: Patricia Colmenares \n" +"Language-Team: Spanish (Latin America) (http://www.transifex.com/projects/p/edx-platform/language/es_419/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2319,7 +2322,7 @@ msgstr "Más" #: common/static/js/vendor/ova/catch/js/catch.js msgid "My Notes" -msgstr "Mis Anotaciones" +msgstr "Mis notas" #: common/static/js/vendor/ova/catch/js/catch.js msgid "Instructor" @@ -2389,18 +2392,33 @@ msgstr "Etiquetas:" msgid "name" msgstr "nombre" +#: lms/djangoapps/teams/static/teams/js/collections/team.js +msgid "open_slots" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/collections/topic.js msgid "team count" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "" +msgstr[1] "" + +#: 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/teams.js +msgid "Create new team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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 "" -"Los equipos de curso están organizados por temas creados por los " -"instructores. Intente unirse un equipo existente antes de decidirse a crear " -"un nuevo equipo." #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "Teams" @@ -2414,6 +2432,14 @@ msgstr "Mis equipos" msgid "Browse" msgstr "Explorar" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "" + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2471,22 +2497,6 @@ msgid "Error generating problem grade report. Please try again." msgstr "" "Error al generar el reporte de calificaciones. Por favor intente nuevamente." -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "Métrica no disponible para visualización" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "Error al generar las distribuciones de calificaciones." - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "Última actualización: <%= timestamp %>" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "<%= num_students %> estudiantes calificados." - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3335,6 +3345,12 @@ msgstr "Su donación no pudo ser enviada." msgid "An error occurred. Please try again later." msgstr "Ocurrió un error. Por favor intente nuevamente más tarde." +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "" +msgstr[1] "" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "No se ha encontrado ninguna coincidencia para \"%s\"." @@ -3348,8 +3364,8 @@ msgstr "Hubo un error, intente buscar de nuevo." msgid "Focus grabber" msgstr "Captura del foco" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." @@ -3357,6 +3373,22 @@ msgstr "" "Ha ocurrido un error. Asegúrese de que está conectado a Internet y luego " "recargue la página." +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "Ocultar notas" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "Notas visibles" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "Mostrar notas" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "Notas ocultas" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3367,22 +3399,6 @@ msgstr "" msgid "Current tab" msgstr "Pestaña actual" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "Ocultar notas" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "Notas visibles" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "Mostrar notas" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "Notas ocultas" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "Ubicación en el curso" @@ -5239,6 +5255,21 @@ msgstr "eliminar todo" msgid "remove" msgstr "eliminar" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "gettext(" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "Gracias! Hemos recibido su pago." @@ -5336,10 +5367,6 @@ msgstr "MENOS..." msgid "LEARN MORE" msgstr "APRENDER MAS" -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "gettext(" - #: lms/templates/discovery/result_item.underscore msgid "Starts" msgstr "Empieza" @@ -6327,10 +6354,6 @@ msgstr "estado" msgid "Common Problem Types" msgstr "Tipos de problemas comunes" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "Problemas comunes con las pistas y los comentarios" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "Añadir nuevo Componente" diff --git a/conf/locale/fr/LC_MESSAGES/django.mo b/conf/locale/fr/LC_MESSAGES/django.mo index 7dd33032e0..5a3fb8ccea 100644 Binary files a/conf/locale/fr/LC_MESSAGES/django.mo and b/conf/locale/fr/LC_MESSAGES/django.mo differ diff --git a/conf/locale/fr/LC_MESSAGES/django.po b/conf/locale/fr/LC_MESSAGES/django.po index 39410528c7..15c6284145 100644 --- a/conf/locale/fr/LC_MESSAGES/django.po +++ b/conf/locale/fr/LC_MESSAGES/django.po @@ -176,10 +176,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:33+0000\n" +"POT-Creation-Date: 2015-07-22 17:45+0000\n" "PO-Revision-Date: 2015-06-19 17:16+0000\n" "Last-Translator: Xavier Antoviaque \n" -"Language-Team: French (http://www.transifex.com/p/edx-platform/language/fr/)\n" +"Language-Team: French (http://www.transifex.com/projects/p/edx-platform/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -201,8 +201,6 @@ msgstr "Discussion" #: cms/djangoapps/contentstore/views/component.py #: lms/djangoapps/class_dashboard/dashboard_data.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Problem" msgstr "Exercice" @@ -304,6 +302,68 @@ msgid "" " Please list each domain on its own line." msgstr "" +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "Mode" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html +msgid "Course" +msgstr "Cours" + +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/annotatable_module.py +#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/combined_open_ended_module.py +#: common/lib/xmodule/xmodule/discussion_module.py +#: common/lib/xmodule/xmodule/html_module.py +#: common/lib/xmodule/xmodule/imageannotation_module.py +#: common/lib/xmodule/xmodule/library_content_module.py +#: common/lib/xmodule/xmodule/lti_module.py +#: common/lib/xmodule/xmodule/peer_grading_module.py +#: common/lib/xmodule/xmodule/split_test_module.py +#: common/lib/xmodule/xmodule/textannotation_module.py +#: common/lib/xmodule/xmodule/videoannotation_module.py +#: common/lib/xmodule/xmodule/word_cloud_module.py +#: cms/templates/container.html cms/templates/library.html +msgid "Display Name" +msgstr "Nom d'affichage" + +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "Prix" + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "Certificat sur l'honneur" @@ -674,11 +734,9 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" -"Si vous ne disposez pas encore d'un compte {platform_name}, cliquez sur " -" S'enregistrer maintenant en haut de la page." #: common/djangoapps/student/views.py msgid "There was an error receiving your login information. Please email us." @@ -1705,23 +1763,6 @@ msgstr "Ne peut pas interpréter '{given_answer}' comme étant un nombre." msgid "XML data for the annotation" msgstr "données XML pour l'annotation" -#: common/lib/xmodule/xmodule/annotatable_module.py -#: common/lib/xmodule/xmodule/capa_base.py -#: common/lib/xmodule/xmodule/combined_open_ended_module.py -#: common/lib/xmodule/xmodule/discussion_module.py -#: common/lib/xmodule/xmodule/html_module.py -#: common/lib/xmodule/xmodule/imageannotation_module.py -#: common/lib/xmodule/xmodule/library_content_module.py -#: common/lib/xmodule/xmodule/lti_module.py -#: common/lib/xmodule/xmodule/peer_grading_module.py -#: common/lib/xmodule/xmodule/split_test_module.py -#: common/lib/xmodule/xmodule/textannotation_module.py -#: common/lib/xmodule/xmodule/videoannotation_module.py -#: common/lib/xmodule/xmodule/word_cloud_module.py -#: cms/templates/container.html cms/templates/library.html -msgid "Display Name" -msgstr "Nom d'affichage" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1851,14 +1892,9 @@ msgstr "Randomisation" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" -"Définit combien de fois les entrées sont randomisées quand un étudiant " -"récupère le problème. Ce paramètre s'applique uniquement aux problèmes " -"reposant sur des valeurs numériques générées aléatoirement. Une valeur par " -"défaut peut être définie dans les paramètres avancés." #: common/lib/xmodule/xmodule/capa_base.py msgid "On Reset" @@ -2517,9 +2553,9 @@ msgid "" " name of the tab (usually the name of the book) as well as the URLs and " "titles of all the chapters in the book." msgstr "" -"Pour les manuels HTML qui apparaissent sous forme d'onglets distincts dans " -"les ressources du cours, entrez le nom de l'onglet (généralement le nom de " -"l'ouvrage) ainsi que les URL et les titres de tous les chapitres du livre." +"Pour les manuels qui apparaissent sous forme d'onglets distincts dans le " +"cours, entrez le nom de l'onglet (généralement le nom de l'ouvrage) ainsi " +"que les URL et les titres de tous les chapitres du manuel." #: common/lib/xmodule/xmodule/course_module.py msgid "Remote Gradebook" @@ -3392,10 +3428,6 @@ msgstr "" msgid "Library Version" msgstr "Version de la bibliothèque" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "Mode" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "" @@ -4027,16 +4059,12 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" -"Indiquez combien de fois les valeurs des variables dans un problème sont " -"réparties au hasard quand un étudiant charge le problème. Les valeurs " -"valides sont \"onreset\", \"toujours\", \"jamais\" et \"par étudiant\". Ce " -"paramètre s'applique uniquement aux problèmes qui ont des valeurs numériques" -" générées de façon aléatoire." #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "Days Early for Beta Users" @@ -4179,6 +4207,8 @@ msgid "" "Indicates whether Student Notes are visible in the course. Students can also" " show or hide their notes in the courseware." msgstr "" +"Indique si les Notes d'étudiant sont visibles dans le cours. Les étudiants " +"peuvent aussi afficher/masquer leur notes de cours." #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "Tag this module as part of an Entrance Exam section" @@ -5116,7 +5146,7 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" @@ -5232,10 +5262,38 @@ msgstr "" msgid "Visit a course wiki to add an article." msgstr "Visitez le wiki d'un cours pour ajouter un article." +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" + #: lms/djangoapps/courseware/tabs.py #: lms/templates/courseware/courseware-error.html msgid "Courseware" -msgstr "Contenu du cours" +msgstr "Cours" #: lms/djangoapps/courseware/tabs.py #: lms/djangoapps/instructor/views/instructor_dashboard.py @@ -5890,7 +5948,6 @@ msgstr "Genre" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/tasks_helper.py -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Level of Education" msgstr "Niveau de formation" @@ -5910,28 +5967,22 @@ msgstr "Cohorte" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5990,29 +6041,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -6066,28 +6116,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -6232,13 +6282,12 @@ msgid "Data Download" msgstr "Téléchargement des données" #: lms/djangoapps/instructor/views/instructor_dashboard.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Analytics" -msgstr "Analyses" +msgid "For analytics about your course, go to {analytics_dashboard_name}." +msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." -msgstr "" +msgid "Analytics" +msgstr "Analyses" #: lms/djangoapps/instructor/views/instructor_dashboard.py #: lms/templates/courseware/legacy_instructor_dashboard.html @@ -6520,7 +6569,6 @@ msgid "Title" msgstr "Titre" #: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "Année de naissance" @@ -6744,7 +6792,7 @@ msgstr "" #: lms/djangoapps/lms_xblock/mixin.py msgid "Courseware Chrome" -msgstr "Ressources de cours Chrome" +msgstr "Cours Chrome" #: lms/djangoapps/lms_xblock/mixin.py msgid "" @@ -6769,8 +6817,8 @@ msgid "" "Enter the tab that is selected in the XBlock. If not set, the Courseware tab" " is selected." msgstr "" -"saisir l'onglet sélectionné dans le XBlock. par défaut, l'onglet du cours en" -" ligne est sélectionné." +"Saisir l'onglet sélectionné dans le XBlock. Si vide, l'onglet Cours est " +"sélectionné." #: lms/djangoapps/lms_xblock/mixin.py msgid "LaTeX Source File Name" @@ -7174,10 +7222,6 @@ msgstr "Commentaires" msgid "University" msgstr "Université" -#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html -msgid "Course" -msgstr "Cours" - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "Date de l'annonce du cours" @@ -7185,7 +7229,7 @@ msgstr "Date de l'annonce du cours" #: lms/djangoapps/shoppingcart/reports.py cms/templates/settings.html #: lms/templates/instructor/instructor_dashboard_2/executive_summary.html msgid "Course Start Date" -msgstr "Date de début du Cours" +msgstr "Date de début du cours" #: lms/djangoapps/shoppingcart/reports.py msgid "Course Registration Close Date" @@ -7963,6 +8007,10 @@ msgstr "" msgid "course_id must be provided" msgstr "" +#: lms/djangoapps/teams/views.py +msgid "The supplied topic id {topic_id} is not valid" +msgstr "" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "" @@ -7972,11 +8020,11 @@ msgid "last_activity is not yet supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The supplied course_id {course_id} is not valid." +msgid "The ordering {} is not supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The ordering {} is not supported" +msgid "The supplied course_id {course_id} is not valid." msgstr "" #: lms/djangoapps/teams/views.py @@ -8034,6 +8082,16 @@ msgstr "" "Il y a eu une erreur pendant le processus de vérification de vos photos " "d'identité." +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "Introduction" @@ -8883,6 +8941,10 @@ msgstr "" msgid "A cohort with the same name already exists." msgstr "Une cohorte avec le même nom existe déjà." +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -8930,6 +8992,20 @@ msgid "" "credit provider." msgstr "" +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "" @@ -9565,9 +9641,7 @@ msgstr "Page non trouvée" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -9704,6 +9778,11 @@ msgstr "" msgid "Course Navigation" msgstr "Menu du cours" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py msgid "Help" @@ -9869,7 +9948,8 @@ msgstr "EN SAVOIR PLUS" msgid "Starts" msgstr "Commence" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "Tableau de bord" @@ -9898,12 +9978,12 @@ msgid "Clear search" msgstr "Effacer la recherche" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" -msgstr "Vous voulez changer les paramètres de votre compte ?" +msgid "Find New Courses" +msgstr "" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." -msgstr "Cliquez sur le menu déroulant ci-dessus." +msgid "Account Status Info" +msgstr "" #: lms/templates/dashboard.html msgid "Order History" @@ -10526,27 +10606,23 @@ msgid "More options dropdown" msgstr "Liste déroulante d'options supplémentaires" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "Paramètres du compte" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" -msgstr "Mon profil" +msgid "Profile" +msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html #: lms/templates/shoppingcart/shopping_cart.html msgid "Shopping Cart" msgstr "Panier" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" -msgstr "Inscription" - #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "Sign in" msgstr "Connexion" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +#: lms/templates/register.html +msgid "Register" +msgstr "Inscription" + #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "" "Warning: Your browser is not fully supported. We strongly " @@ -10568,10 +10644,6 @@ msgstr "Administrateur système" msgid "Schools" msgstr "Écoles" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "Inscription" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -11638,6 +11710,11 @@ msgstr "" msgid "I completed the {course_title} course on {platform_name}." msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "" @@ -11646,6 +11723,15 @@ msgstr "" msgid "Post on Facebook" msgstr "Poster sur Facebook" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "Partager sur Twitter" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "Ajouter au profil LinkedIn" @@ -11897,6 +11983,10 @@ msgstr "{chapter}, chapitre en cours" msgid "due {date}" msgstr "Echéance le {date}" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "" + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -11920,7 +12010,7 @@ msgstr "Vous êtes inscrit à ce cours" #: lms/templates/courseware/course_about.html msgid "View Courseware" -msgstr "Voir le Cours" +msgstr "Voir le cours" #: lms/templates/courseware/course_about.html msgid "This course is in your cart." @@ -12000,10 +12090,6 @@ msgstr "Fin des cours" msgid "Estimated Effort" msgstr "Effort estimé" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "Prix" - #: lms/templates/courseware/course_about.html msgid "Prerequisites" msgstr "Pré-requis" @@ -12032,12 +12118,24 @@ msgstr "" msgid "View this course as:" msgstr "Voir ce cours comme:" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "Étudiant dans {content_group}" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" +msgid "Username or email:" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." msgstr "" #: lms/templates/courseware/course_navigation.html @@ -12074,6 +12172,10 @@ msgstr "Consultez les cours de {platform_name}." msgid "{platform_name} Logo" msgstr "Logo {platform_name}" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "" @@ -12373,78 +12475,6 @@ msgid "To send email, visit the Email section of the Instructor Dashboard." msgstr "" "Pour envoyer un e-mail, visitez la section E-mail de l'onglet Instructeur." -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "Aucune analyse disponible pour le moment." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "Activité étudiant jour par jour" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "Jour" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "Étudiants" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "Distribution des scores pour les exercices" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "Maximum" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "Points gagnés (nombre d'étudiants)" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "Il n'y a pas de données disponibles pour l'instant." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "" -"Chargement des graphiques à jour ; en fonction de la taille de votre classe," -" cela peut prendre plusieurs minutes." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "Nombre d'étudiants qui ont ouvert une sous-section" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr "Répartition des notes par problème" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "Cette section ne contient pas de problèmes." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "Étudiants ayant correctement répondu" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "Nombre d'étudiants" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" -"Distribution des étudiants par pays, tous les cours, 12 septembre au 17 " -"octobre, serveur 1 (montré ici comme un exemple) :" - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "Tâches Enseignant en Attente" @@ -12508,7 +12538,7 @@ msgstr "A propos de {course_number}" #: lms/templates/courseware/mktg_course_about.html msgid "Access Courseware" -msgstr "Accéder au contenu du Cours" +msgstr "Accéder au cours" #: lms/templates/courseware/mktg_course_about.html msgid "You Are Enrolled" @@ -12555,7 +12585,7 @@ msgstr "Progression {course_number}" #: lms/templates/courseware/progress.html msgid "Course Progress" -msgstr "Progression dans le cours" +msgstr "Progression" #: lms/templates/courseware/progress.html msgid "View Grading in studio" @@ -12563,7 +12593,7 @@ msgstr "Voir la notation dans Studio" #: lms/templates/courseware/progress.html msgid "Course Progress for Student '{username}' ({email})" -msgstr "Progression dans le cours de l'étudiant '{username}' ({email})" +msgstr "Progression pour '{username}' ({email})" #: lms/templates/courseware/progress.html msgid "Your certificate is available" @@ -12613,11 +12643,12 @@ msgid "Requirements for Course Credit" msgstr "" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." +msgid "{student_name}, you are no longer eligible for credit in this course." msgstr "" #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." +msgid "" +"{student_name}, you have met the requirements for credit in this course." msgstr "" #: lms/templates/courseware/progress.html @@ -12684,6 +12715,46 @@ msgstr "" "Vous étiez récemment dans {section_link}. Si vous avez terminé, nous vous " "invitons à poursuivre l'exploration du cours sur le menu à gauche." +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "Bonjour {name}," + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "" + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -12819,10 +12890,6 @@ msgstr "Partager sur Facebook" msgid "I'm learning on {platform_name}:" msgstr "" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "Partager sur Twitter" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "" @@ -13768,11 +13835,6 @@ msgstr "" msgid "You have been invited to a beta test for {course_name}" msgstr "Vous avez été invité à un bêta-test de {course_name}" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "Bonjour {name}," - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "Merci pour votre achat de" @@ -14306,7 +14368,7 @@ msgstr "" #: lms/templates/emails/reverification_processed.txt msgid "To go to the courseware, select the following link:" -msgstr "" +msgstr "Pour voir le cours, sélectionnez le lien suivant:" #: lms/templates/emails/reverification_processed.txt msgid "" @@ -15306,34 +15368,6 @@ msgstr "" msgid "Send me a copy of the invoice" msgstr "Envoyez-moi une copie de la facture" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "Distribution des scores" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "" -"Le tableau ci-dessous affiche la répartition des notes pour chaque exercice " -"standard de votre cours, par URL du nom de l'exercice." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "" -"Les scores sont affichés sans pondération, donc si votre exercice contient 2" -" questions, il sera affiché comme ayant un total de 2 points." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "Chargement de la liste des exercices..." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "Répartition selon le sexe" - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "Tableau de bord enseignant" @@ -15561,6 +15595,10 @@ msgstr "" msgid "Add CCX Coach" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "Il n'y a pas de données disponibles pour l'instant." + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "Utilisez Recharger les graphiques pour rafraîchir les graphiques. " @@ -15618,6 +15656,10 @@ msgid "Download Problem Data for all Problems as a CSV" msgstr "" "Télécharger les données du problème pour tous les problèmes en tant que CSV" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr "Répartition des notes par problème" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "" @@ -15632,6 +15674,10 @@ msgstr "" "Ceci est une liste partielle, téléchargez le fichier .csv pour voir tous les" " étudiants." +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "Cette section ne contient pas de problèmes." + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "Envoyer l'e-mail" @@ -16457,6 +16503,10 @@ msgstr "Prix par étudiant" msgid "Discount Applied:" msgstr "Remise Appliquée:" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "Étudiants" + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -16705,6 +16755,10 @@ msgstr "" msgid "Currently the {platform_name} servers are overloaded" msgstr "Les serveurs de {platform_name} sont actuellement surchargés" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "Paramètres du compte" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "Veuillez patienter" @@ -16814,16 +16868,26 @@ msgstr "" msgid "Re-Verify for {course_name}" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." msgstr "" +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" + #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." msgstr "" @@ -17247,7 +17311,7 @@ msgstr "Glissez pour modifier l'ordre" #: cms/templates/container.html msgid "Open the courseware in the LMS" -msgstr "Ouvrir le contenu du cours dans le LMS" +msgstr "Ouvrir le cours dans le LMS" #: cms/templates/container.html msgid "View Live Version" @@ -17255,7 +17319,7 @@ msgstr "Aperçu réel" #: cms/templates/container.html msgid "Preview the courseware in the LMS" -msgstr "" +msgstr "Prévisualiser le cours dans le LMS" #: cms/templates/container.html msgid "Adding components" @@ -17575,7 +17639,7 @@ msgstr "Déplier toutes les Sections" #: cms/templates/course_outline.html msgid "Click to open the courseware in the LMS in a new tab" -msgstr "" +msgstr "Cliquez pour ouvrir le cours dans le LMS et un nouvel onglet" #: cms/templates/course_outline.html cms/templates/edit-tabs.html #: cms/templates/index.html @@ -17706,9 +17770,8 @@ msgid "" "textbooks and custom pages that you create." msgstr "" "Les pages sont répertoriés horizontalement en haut de votre cours. Les pages" -" par défaut (ressources de cours, informations sur le cours, Discussion, " -"Wiki, et avancement) sont suivies par les manuels et les pages " -"personnalisées que vous créez." +" par défaut (Cours, Infos, Discussions, Wiki, et Progression) sont suivies " +"par les manuels et les pages personnalisées que vous créez." #: cms/templates/edit-tabs.html msgid "Custom pages" @@ -17756,9 +17819,8 @@ msgid "" "textbooks and custom pages." msgstr "" "Les pages apparaissent dans la barre de navigation en haut de votre cours. " -"Les pages par défaut (ressources de cours, informations sur le cours, " -"Discussion, Wiki, et avancement) sont suivies par les manuels et les pages " -"personnalisées." +"Les pages par défaut (Cours, Infos, Discussions, Wiki, et Progression) sont" +" suivies par les manuels et les pages personnalisées." #: cms/templates/edit-tabs.html cms/templates/howitworks.html msgid "close modal" @@ -18059,6 +18121,10 @@ msgid "" "create cohort-specific courseware. In other words, you can customize the " "content that particular cohorts see in your course." msgstr "" +"Si vous avez activé les cohortes pour le cours, vous pouvez utiliser les " +"groupes de contenu pour créer des modules de cours spécifiques à des " +"cohortes. En d'autres termes, vous pouvez personnaliser le contenu que " +"certaines cohortes peuvent voir dans le cours." #: cms/templates/group_configurations.html msgid "" @@ -20026,10 +20092,6 @@ msgstr "Exporter" msgid "Current Library:" msgstr "Bibliothèque actuelle :" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "Compte" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "" diff --git a/conf/locale/fr/LC_MESSAGES/djangojs.mo b/conf/locale/fr/LC_MESSAGES/djangojs.mo index a89a57644e..6124f2166e 100644 Binary files a/conf/locale/fr/LC_MESSAGES/djangojs.mo and b/conf/locale/fr/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/fr/LC_MESSAGES/djangojs.po b/conf/locale/fr/LC_MESSAGES/djangojs.po index ddb4fa7101..e0de7333f7 100644 --- a/conf/locale/fr/LC_MESSAGES/djangojs.po +++ b/conf/locale/fr/LC_MESSAGES/djangojs.po @@ -6,6 +6,7 @@ # Translators: # SALHI Aissam , 2014 # anaseha , 2014 +# Axel Billot , 2015 # Bertrand Marron , 2014 # Christopher Castermane , 2014 # Daniel Le Berre, 2015 @@ -109,10 +110,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:31+0000\n" -"PO-Revision-Date: 2015-07-10 19:12+0000\n" -"Last-Translator: Sarina Canelake \n" -"Language-Team: French (http://www.transifex.com/p/edx-platform/language/fr/)\n" +"POT-Creation-Date: 2015-07-22 17:43+0000\n" +"PO-Revision-Date: 2015-07-15 21:53+0000\n" +"Last-Translator: moocit-france \n" +"Language-Team: French (http://www.transifex.com/projects/p/edx-platform/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -1886,6 +1887,8 @@ msgid "" "Activating an item in this group will spool the video to the corresponding " "time point. To skip transcript, go to previous item." msgstr "" +"L'activation d'un élément de ce groupe jouera la vidéo à partir de ce point." +" Pour passer la transcription, allez à l'élément précédent." #: common/lib/xmodule/xmodule/js/src/video/09_video_caption.js msgid "Caption will be displayed when " @@ -2418,14 +2421,32 @@ msgstr "Balises : " msgid "name" msgstr "nom" +#: lms/djangoapps/teams/static/teams/js/collections/team.js +msgid "open_slots" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/collections/topic.js msgid "team count" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "" +msgstr[1] "" + +#: 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/teams.js +msgid "Create new team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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 @@ -2440,6 +2461,14 @@ msgstr "Mes équipes" msgid "Browse" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "" + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2496,22 +2525,6 @@ msgstr "" "Erreur lors de la génération du rapport des notes. Merci d’essayer à " "nouveau." -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "Affichage des métriques non disponible" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "Erreur lors de la récupération de la distribution des notes." - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "Dernière mise à jour: <%= timestamp %>" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "<%= num_students %> étudiants ont réussi." - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3343,6 +3356,12 @@ msgstr "Votre don n'a pas pu être soumis" msgid "An error occurred. Please try again later." msgstr "Une erreur est survenue. Veuillez essayer de nouveau plus tard." +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "" +msgstr[1] "" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "Nous ne trouvons pas de résultat pour \"%s\"." @@ -3350,14 +3369,14 @@ msgstr "Nous ne trouvons pas de résultat pour \"%s\"." #: lms/static/js/discovery/form.js #: lms/templates/search/search_error.underscore msgid "There was an error, try searching again." -msgstr "Il y a eu une erreur, essayer de chercher à nouveau." +msgstr "Une erreur est survenue, essayez à nouveau." #: lms/static/js/edxnotes/plugins/accessibility.js msgid "Focus grabber" msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." @@ -3365,6 +3384,22 @@ msgstr "" "Une erreur est survenue. Assurez-vous que vous êtes bien connecté à Internet" " et essayez de rafraîchir la page." +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "Masquer les notes" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "Notes visibles" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "Afficher les notes" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "Notes masquées" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3376,22 +3411,6 @@ msgstr "" msgid "Current tab" msgstr "Onglet en cours" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "Masquer les notes" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "Notes visibles" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "Afficher les notes" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "Notes masquées" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "Emplacement dans le cours" @@ -3412,7 +3431,7 @@ msgstr "" #. translated. #: lms/static/js/edxnotes/views/tabs/tags.js msgid "[no tags]" -msgstr "" +msgstr "[aucun tag]" #: lms/static/js/groups/views/cohort_discussions.js #: lms/static/js/groups/views/cohort_discussions_course_wide.js @@ -4119,8 +4138,7 @@ msgstr "Erreur de la sauvegarde d'OpenAssessment" #: cms/static/js/base.js cms/templates/js/checklist.underscore msgid "This link will open in a new browser window/tab" msgstr "" -"Le lien va s'ouvrir dans une nouvelle fenêtre ou un nouvel onglet du " -"navigateur." +"Ce lien s'ouvrira dans une nouvelle fenêtre ou onglet de votre navigateur" #: cms/static/js/base.js msgid "This link will open in a modal window" @@ -4850,8 +4868,8 @@ msgid "" "Deleting a textbook cannot be undone and once deleted any reference to it in" " your courseware's navigation will also be removed." msgstr "" -"Supprimer un livre est irréversible et toutes les références depuis le cours" -" seront également détruites." +"Supprimer un manuel est irréversible, toutes les références dans le cours " +"seront également supprimées." #: cms/static/js/views/uploads.js #: cms/templates/js/metadata-file-uploader-item.underscore @@ -5206,6 +5224,21 @@ msgstr "tout supprimer" msgid "remove" msgstr "supprimer" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "Merci ! Nous avons reçu votre paiement." @@ -5303,10 +5336,6 @@ msgstr "Moins ..." msgid "LEARN MORE" msgstr "EN SAVOIR PLUS" -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "" - #: lms/templates/discovery/result_item.underscore msgid "Starts" msgstr "Débute" @@ -6145,7 +6174,7 @@ msgstr "" #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" -msgstr "" +msgstr "Retour au Tableau de bord" #: lms/templates/verify_student/review_photos_step.underscore msgid "Review Your Photos" @@ -6238,10 +6267,6 @@ msgstr "statut" msgid "Common Problem Types" msgstr "Types d'exercices classiques" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "Ajouter un nouveau Composant" @@ -6761,7 +6786,7 @@ msgstr "" msgid "" "The following message will be displayed at the bottom of the courseware " "pages within your course:" -msgstr "" +msgstr "Le message suivant sera affiché au bas des pages du cours:" #: cms/templates/js/license-selector.underscore msgid "Creative Commons licensed content, with terms as follow:" diff --git a/conf/locale/he/LC_MESSAGES/django.mo b/conf/locale/he/LC_MESSAGES/django.mo index 02e6ef4675..8ba5b436c6 100644 Binary files a/conf/locale/he/LC_MESSAGES/django.mo and b/conf/locale/he/LC_MESSAGES/django.mo differ diff --git a/conf/locale/he/LC_MESSAGES/django.po b/conf/locale/he/LC_MESSAGES/django.po index 394d0c681d..7c1da6fa95 100644 --- a/conf/locale/he/LC_MESSAGES/django.po +++ b/conf/locale/he/LC_MESSAGES/django.po @@ -7,6 +7,7 @@ # Bentsi Magidovich , 2015 # Nadav Stark , 2015 # shay nativ , 2015 +# yuval zana, 2015 # #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-# # edX translation file. # Copyright (C) 2015 EdX @@ -60,10 +61,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:33+0000\n" +"POT-Creation-Date: 2015-07-22 17:45+0000\n" "PO-Revision-Date: 2015-05-28 20:00+0000\n" "Last-Translator: Nadav Stark \n" -"Language-Team: Hebrew (http://www.transifex.com/p/edx-platform/language/he/)\n" +"Language-Team: Hebrew (http://www.transifex.com/projects/p/edx-platform/language/he/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -85,8 +86,6 @@ msgstr "" #: cms/djangoapps/contentstore/views/component.py #: lms/djangoapps/class_dashboard/dashboard_data.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Problem" msgstr "" @@ -188,6 +187,69 @@ msgid "" " Please list each domain on its own line." msgstr "" +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py +msgid "Course" +msgstr "קורס" + +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/annotatable_module.py +#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/combined_open_ended_module.py +#: common/lib/xmodule/xmodule/discussion_module.py +#: common/lib/xmodule/xmodule/html_module.py +#: common/lib/xmodule/xmodule/imageannotation_module.py +#: common/lib/xmodule/xmodule/library_content_module.py +#: common/lib/xmodule/xmodule/lti_module.py +#: common/lib/xmodule/xmodule/peer_grading_module.py +#: common/lib/xmodule/xmodule/split_test_module.py +#: common/lib/xmodule/xmodule/textannotation_module.py +#: common/lib/xmodule/xmodule/videoannotation_module.py +#: common/lib/xmodule/xmodule/word_cloud_module.py +#: cms/templates/container.html cms/templates/library.html +msgid "Display Name" +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "" @@ -548,8 +610,8 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" #: common/djangoapps/student/views.py @@ -1509,23 +1571,6 @@ msgstr "" msgid "XML data for the annotation" msgstr "" -#: common/lib/xmodule/xmodule/annotatable_module.py -#: common/lib/xmodule/xmodule/capa_base.py -#: common/lib/xmodule/xmodule/combined_open_ended_module.py -#: common/lib/xmodule/xmodule/discussion_module.py -#: common/lib/xmodule/xmodule/html_module.py -#: common/lib/xmodule/xmodule/imageannotation_module.py -#: common/lib/xmodule/xmodule/library_content_module.py -#: common/lib/xmodule/xmodule/lti_module.py -#: common/lib/xmodule/xmodule/peer_grading_module.py -#: common/lib/xmodule/xmodule/split_test_module.py -#: common/lib/xmodule/xmodule/textannotation_module.py -#: common/lib/xmodule/xmodule/videoannotation_module.py -#: common/lib/xmodule/xmodule/word_cloud_module.py -#: cms/templates/container.html cms/templates/library.html -msgid "Display Name" -msgstr "" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1644,9 +1689,8 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" #: common/lib/xmodule/xmodule/capa_base.py @@ -3019,10 +3063,6 @@ msgstr "" msgid "Library Version" msgstr "" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "" @@ -3585,10 +3625,11 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py @@ -4588,7 +4629,7 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" @@ -4704,6 +4745,34 @@ msgstr "" msgid "Visit a course wiki to add an article." msgstr "" +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" + #: lms/djangoapps/courseware/tabs.py #: lms/templates/courseware/courseware-error.html msgid "Courseware" @@ -5335,7 +5404,6 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/tasks_helper.py -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Level of Education" msgstr "" @@ -5355,28 +5423,22 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5435,29 +5497,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5511,28 +5572,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5664,12 +5725,11 @@ msgid "Data Download" msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Analytics" +msgid "For analytics about your course, go to {analytics_dashboard_name}." msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." +msgid "Analytics" msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py @@ -5942,7 +6002,6 @@ msgid "Title" msgstr "" #: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "" @@ -6554,10 +6613,6 @@ msgstr "" msgid "University" msgstr "אוניברסיטה" -#: lms/djangoapps/shoppingcart/reports.py -msgid "Course" -msgstr "קורס" - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "" @@ -7259,6 +7314,10 @@ msgstr "" msgid "course_id must be provided" msgstr "" +#: lms/djangoapps/teams/views.py +msgid "The supplied topic id {topic_id} is not valid" +msgstr "" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "" @@ -7268,11 +7327,11 @@ msgid "last_activity is not yet supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The supplied course_id {course_id} is not valid." +msgid "The ordering {} is not supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The ordering {} is not supported" +msgid "The supplied course_id {course_id} is not valid." msgstr "" #: lms/djangoapps/teams/views.py @@ -7325,6 +7384,16 @@ msgstr "" msgid "There was an error verifying your ID photos." msgstr "" +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "" @@ -8116,6 +8185,10 @@ msgstr "" msgid "A cohort with the same name already exists." msgstr "" +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -8163,6 +8236,20 @@ msgid "" "credit provider." msgstr "" +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "" @@ -8759,9 +8846,7 @@ msgstr "העמוד לא נמצא" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -8897,6 +8982,11 @@ msgstr "" msgid "Course Navigation" msgstr "" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py msgid "Help" @@ -9057,7 +9147,8 @@ msgstr "" msgid "Starts" msgstr "" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "" @@ -9086,11 +9177,11 @@ msgid "Clear search" msgstr "" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" +msgid "Find New Courses" msgstr "" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." +msgid "Account Status Info" msgstr "" #: lms/templates/dashboard.html @@ -9673,12 +9764,7 @@ msgid "More options dropdown" msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" +msgid "Profile" msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html @@ -9686,12 +9772,13 @@ msgstr "" msgid "Shopping Cart" msgstr "" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +msgid "Sign in" msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "Sign in" +#: lms/templates/register.html +msgid "Register" msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html @@ -9713,10 +9800,6 @@ msgstr "" msgid "Schools" msgstr "" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "הרשם עכשיו" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -10718,6 +10801,11 @@ msgstr "" msgid "I completed the {course_title} course on {platform_name}." msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "" @@ -10726,6 +10814,15 @@ msgstr "" msgid "Post on Facebook" msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "" @@ -10968,6 +11065,10 @@ msgstr "" msgid "due {date}" msgstr "" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "" + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -11067,10 +11168,6 @@ msgstr "" msgid "Estimated Effort" msgstr "" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Prerequisites" msgstr "" @@ -11099,12 +11196,24 @@ msgstr "" msgid "View this course as:" msgstr "" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" +msgid "Username or email:" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." msgstr "" #: lms/templates/courseware/course_navigation.html @@ -11139,6 +11248,10 @@ msgstr "סייר בקורסים מ{platform_name}." msgid "{platform_name} Logo" msgstr "" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "" @@ -11408,74 +11521,6 @@ msgstr "" msgid "To send email, visit the Email section of the Instructor Dashboard." msgstr "" -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "" @@ -11642,11 +11687,12 @@ msgid "Requirements for Course Credit" msgstr "" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." +msgid "{student_name}, you are no longer eligible for credit in this course." msgstr "" #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." +msgid "" +"{student_name}, you have met the requirements for credit in this course." msgstr "" #: lms/templates/courseware/progress.html @@ -11711,6 +11757,46 @@ msgid "" "another section on the left." msgstr "" +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "" + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -11826,10 +11912,6 @@ msgstr "" msgid "I'm learning on {platform_name}:" msgstr "" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "" @@ -12718,11 +12800,6 @@ msgstr "" msgid "You have been invited to a beta test for {course_name}" msgstr "" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "" - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "" @@ -14122,30 +14199,6 @@ msgstr "" msgid "Send me a copy of the invoice" msgstr "" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "" - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "" @@ -14364,6 +14417,10 @@ msgstr "" msgid "Add CCX Coach" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "" @@ -14412,6 +14469,10 @@ msgstr "" msgid "Download Problem Data for all Problems as a CSV" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "" @@ -14424,6 +14485,10 @@ msgstr "" msgid "This is a partial list, to view all students download as a csv." msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "" @@ -15184,6 +15249,10 @@ msgstr "" msgid "Discount Applied:" msgstr "" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "" + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -15419,6 +15488,10 @@ msgstr "" msgid "Currently the {platform_name} servers are overloaded" msgstr "" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "" @@ -15522,16 +15595,26 @@ msgstr "" msgid "Re-Verify for {course_name}" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." msgstr "" +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" + #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." msgstr "" @@ -18463,10 +18546,6 @@ msgstr "" msgid "Current Library:" msgstr "" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "" diff --git a/conf/locale/he/LC_MESSAGES/djangojs.mo b/conf/locale/he/LC_MESSAGES/djangojs.mo index cbcb36254a..d01a23e5ca 100644 Binary files a/conf/locale/he/LC_MESSAGES/djangojs.mo and b/conf/locale/he/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/he/LC_MESSAGES/djangojs.po b/conf/locale/he/LC_MESSAGES/djangojs.po index eaa9df6810..b581b5bff0 100644 --- a/conf/locale/he/LC_MESSAGES/djangojs.po +++ b/conf/locale/he/LC_MESSAGES/djangojs.po @@ -44,10 +44,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:31+0000\n" -"PO-Revision-Date: 2015-07-10 19:12+0000\n" +"POT-Creation-Date: 2015-07-22 17:43+0000\n" +"PO-Revision-Date: 2015-07-14 14:36+0000\n" "Last-Translator: Sarina Canelake \n" -"Language-Team: Hebrew (http://www.transifex.com/p/edx-platform/language/he/)\n" +"Language-Team: Hebrew (http://www.transifex.com/projects/p/edx-platform/language/he/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2259,19 +2259,38 @@ msgstr "" msgid "Tags:" 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" msgstr "" +#: lms/djangoapps/teams/static/teams/js/collections/team.js +msgid "open_slots" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/collections/topic.js msgid "team count" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "" +msgstr[1] "" + +#: 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/teams.js +msgid "Create new team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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 @@ -2286,6 +2305,14 @@ msgstr "" msgid "Browse" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "" + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2338,22 +2365,6 @@ msgstr "" msgid "Error generating problem grade report. Please try again." msgstr "" -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "" - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3096,6 +3107,12 @@ msgstr "" msgid "An error occurred. Please try again later." msgstr "" +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "" +msgstr[1] "" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "" @@ -3109,13 +3126,29 @@ msgstr "" msgid "Focus grabber" msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3125,22 +3158,6 @@ msgstr "" msgid "Current tab" msgstr "" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "" @@ -4862,6 +4879,21 @@ msgstr "" msgid "remove" msgstr "" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "" @@ -4954,10 +4986,6 @@ msgstr "" msgid "LEARN MORE" msgstr "" -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "" - #: lms/templates/discovery/result_item.underscore msgid "Starts" msgstr "" @@ -5841,10 +5869,6 @@ msgstr "" msgid "Common Problem Types" msgstr "" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "" diff --git a/conf/locale/hi/LC_MESSAGES/django.mo b/conf/locale/hi/LC_MESSAGES/django.mo index d78b383800..ece669709c 100644 Binary files a/conf/locale/hi/LC_MESSAGES/django.mo and b/conf/locale/hi/LC_MESSAGES/django.mo differ diff --git a/conf/locale/hi/LC_MESSAGES/django.po b/conf/locale/hi/LC_MESSAGES/django.po index d35011c398..68f129fb97 100644 --- a/conf/locale/hi/LC_MESSAGES/django.po +++ b/conf/locale/hi/LC_MESSAGES/django.po @@ -72,10 +72,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:33+0000\n" +"POT-Creation-Date: 2015-07-22 17:45+0000\n" "PO-Revision-Date: 2015-06-28 20:21+0000\n" "Last-Translator: ria1234 \n" -"Language-Team: Hindi (http://www.transifex.com/p/edx-platform/language/hi/)\n" +"Language-Team: Hindi (http://www.transifex.com/projects/p/edx-platform/language/hi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -91,10 +91,10 @@ msgstr "" msgid "Discussion" msgstr "चर्चा" -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html +#: cms/djangoapps/contentstore/views/component.py +#: lms/djangoapps/class_dashboard/dashboard_data.py msgid "Problem" -msgstr "समस्या" +msgstr "" #: cms/djangoapps/contentstore/views/component.py #: common/lib/xmodule/xmodule/video_module/video_module.py @@ -193,6 +193,69 @@ msgid "" " Please list each domain on its own line." msgstr "" +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py +msgid "Course" +msgstr "पाठ्यक्रम" + +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/annotatable_module.py +#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/combined_open_ended_module.py +#: common/lib/xmodule/xmodule/discussion_module.py +#: common/lib/xmodule/xmodule/html_module.py +#: common/lib/xmodule/xmodule/imageannotation_module.py +#: common/lib/xmodule/xmodule/library_content_module.py +#: common/lib/xmodule/xmodule/lti_module.py +#: common/lib/xmodule/xmodule/peer_grading_module.py +#: common/lib/xmodule/xmodule/split_test_module.py +#: common/lib/xmodule/xmodule/textannotation_module.py +#: common/lib/xmodule/xmodule/videoannotation_module.py +#: common/lib/xmodule/xmodule/word_cloud_module.py +#: cms/templates/container.html cms/templates/library.html +msgid "Display Name" +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "ऑनर कोड प्रमाणपत्र" @@ -552,8 +615,8 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" #: common/djangoapps/student/views.py @@ -1524,23 +1587,6 @@ msgstr "'{given_answer}' की व्याख्या एक संख्य msgid "XML data for the annotation" msgstr "" -#: common/lib/xmodule/xmodule/annotatable_module.py -#: common/lib/xmodule/xmodule/capa_base.py -#: common/lib/xmodule/xmodule/combined_open_ended_module.py -#: common/lib/xmodule/xmodule/discussion_module.py -#: common/lib/xmodule/xmodule/html_module.py -#: common/lib/xmodule/xmodule/imageannotation_module.py -#: common/lib/xmodule/xmodule/library_content_module.py -#: common/lib/xmodule/xmodule/lti_module.py -#: common/lib/xmodule/xmodule/peer_grading_module.py -#: common/lib/xmodule/xmodule/split_test_module.py -#: common/lib/xmodule/xmodule/textannotation_module.py -#: common/lib/xmodule/xmodule/videoannotation_module.py -#: common/lib/xmodule/xmodule/word_cloud_module.py -#: cms/templates/container.html cms/templates/library.html -msgid "Display Name" -msgstr "" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1657,9 +1703,8 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" #: common/lib/xmodule/xmodule/capa_base.py @@ -3040,10 +3085,6 @@ msgstr "" msgid "Library Version" msgstr "" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "" @@ -3606,10 +3647,11 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py @@ -4621,7 +4663,7 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" @@ -4736,6 +4778,34 @@ msgstr "" msgid "Visit a course wiki to add an article." msgstr "कोई एक लेख जोड़ने के लिए पाठ्यक्रम विकी पर जाएं।" +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" + #: lms/djangoapps/courseware/tabs.py #: lms/templates/courseware/courseware-error.html msgid "Courseware" @@ -5381,7 +5451,6 @@ msgstr "लिंग" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/tasks_helper.py -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Level of Education" msgstr "शिक्षा का स्तर" @@ -5401,28 +5470,22 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5481,29 +5544,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5557,28 +5619,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5709,13 +5771,12 @@ msgid "Data Download" msgstr "डेटा डाउनलोड" #: lms/djangoapps/instructor/views/instructor_dashboard.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Analytics" -msgstr "एनेलिटिक्स" +msgid "For analytics about your course, go to {analytics_dashboard_name}." +msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." -msgstr "" +msgid "Analytics" +msgstr "एनेलिटिक्स" #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Metrics" @@ -5985,7 +6046,6 @@ msgid "Title" msgstr "शीर्षक" #: lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "जन्म का वर्ष" @@ -6616,10 +6676,6 @@ msgstr "टिप्पणियां" msgid "University" msgstr "विश्वविद्यालय" -#: lms/djangoapps/shoppingcart/reports.py -msgid "Course" -msgstr "पाठ्यक्रम" - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "पाठ्यक्रम की घोषणा की तारीख " @@ -7379,6 +7435,10 @@ msgstr "" msgid "course_id must be provided" msgstr "" +#: lms/djangoapps/teams/views.py +msgid "The supplied topic id {topic_id} is not valid" +msgstr "" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "" @@ -7388,11 +7448,11 @@ msgid "last_activity is not yet supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The supplied course_id {course_id} is not valid." +msgid "The ordering {} is not supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The ordering {} is not supported" +msgid "The supplied course_id {course_id} is not valid." msgstr "" #: lms/djangoapps/teams/views.py @@ -7447,6 +7507,16 @@ msgstr "" msgid "There was an error verifying your ID photos." msgstr "आपके आईडी की फ़ोटोओं की पुष्टि करने में त्रुटि हुई।" +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "" @@ -8285,6 +8355,10 @@ msgstr "" msgid "A cohort with the same name already exists." msgstr "" +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -8332,6 +8406,20 @@ msgid "" "credit provider." msgstr "" +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "" @@ -8910,9 +8998,7 @@ msgstr "यह पेज मौजूद नहीं है" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -9050,6 +9136,11 @@ msgstr "" msgid "Course Navigation" msgstr "पाठ्यक्रम नेविगेशन" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py msgid "Help" @@ -9210,7 +9301,8 @@ msgstr "" msgid "Starts" msgstr "" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "डैशबोर्ड" @@ -9239,11 +9331,11 @@ msgid "Clear search" msgstr "" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" +msgid "Find New Courses" msgstr "" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." +msgid "Account Status Info" msgstr "" #: lms/templates/dashboard.html @@ -9856,12 +9948,7 @@ msgid "More options dropdown" msgstr "और विकल्पों के लिए ड्रॉपडाउन करें" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" +msgid "Profile" msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html @@ -9869,14 +9956,15 @@ msgstr "" msgid "Shopping Cart" msgstr "" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" -msgstr "रजिस्टर करें" - #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "Sign in" msgstr "" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +#: lms/templates/register.html +msgid "Register" +msgstr "रजिस्टर करें" + #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "" "Warning: Your browser is not fully supported. We strongly " @@ -9896,10 +9984,6 @@ msgstr "" msgid "Schools" msgstr "विश्वविद्यालय" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "पंजीकरण करें" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -10944,6 +11028,11 @@ msgstr "" msgid "I completed the {course_title} course on {platform_name}." msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "" @@ -10952,6 +11041,15 @@ msgstr "" msgid "Post on Facebook" msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "" @@ -11201,6 +11299,10 @@ msgstr "{chapter}, मौजूदा अध्याय" msgid "due {date}" msgstr "अंतिम तारीख़ {date}" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "" + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -11304,10 +11406,6 @@ msgstr "कक्षाएं खत्म" msgid "Estimated Effort" msgstr "अनुमानित प्रयास" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Prerequisites" msgstr "आवश्यकताएं" @@ -11336,12 +11434,24 @@ msgstr "" msgid "View this course as:" msgstr "" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" +msgid "Username or email:" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." msgstr "" #: lms/templates/courseware/course_navigation.html @@ -11376,6 +11486,10 @@ msgstr "" msgid "{platform_name} Logo" msgstr "" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "" @@ -11641,76 +11755,6 @@ msgstr "" msgid "To send email, visit the Email section of the Instructor Dashboard." msgstr "" -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "इस वक्त कोई एनलिटिक्स उपलब्ध नहीं हैं।" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "छात्रों की हर दिन की क्रिया " - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "दिन" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "छात्र" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "अधिकतम" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "अंक अर्जित (Num Students)" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "इस वक्त कोई डेटा दिखाने के लिए नहीं हैं।" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "" -"आपके लिए नवीनतम ग्राफ़ लोड हो रहा है; अगर आपकी कक्षा में ज़्यादा मात्रा में " -"छात्र हैं तो लोड होने में थोड़ा वक्त लग सकता है।" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "उन छात्रों की संख्या जिन्होंने एक अनुभाग खोला" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr " श्रेणी वितरण प्रति समस्या" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "इस भाग में कोई समस्याएं नहीं हैं।" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "छात्र जो सही जवाब दे रहे हैं" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "छात्रों की संख्या" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "प्रशिक्षक कार्य जो कि अभी पूरे नहीं हुए हैं" @@ -11877,11 +11921,12 @@ msgid "Requirements for Course Credit" msgstr "" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." +msgid "{student_name}, you are no longer eligible for credit in this course." msgstr "" #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." +msgid "" +"{student_name}, you have met the requirements for credit in this course." msgstr "" #: lms/templates/courseware/progress.html @@ -11948,6 +11993,46 @@ msgstr "" "हाल ही में आप {section_link} में थे। अगर वहां आप का काम पूरा हो गया हो तो " "स्क्रीन की बाई तरफ़ से कोई दूसरा भाग चुनें।" +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "" + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -12082,10 +12167,6 @@ msgstr "" msgid "I'm learning on {platform_name}:" msgstr "" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "" @@ -12987,11 +13068,6 @@ msgstr "" msgid "You have been invited to a beta test for {course_name}" msgstr "" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "" - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "" @@ -14417,34 +14493,6 @@ msgstr "" msgid "Send me a copy of the invoice" msgstr "" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "" -"नीचे दिया गया चार्ट, जो कि समस्या के URL के मुताबिक दिया गया है, यह दिखाता " -"है कि आपकी कक्षा में हर मानक समस्या के लिए स्कोर किस तरह से बांटा गया है।" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "" -"दिखाए जा रहे स्कोर पर कोई भार नहीं जोड़ा गया हैं, तो अगर आपकी समस्या में 2 " -"सवाल हैं, तो जो स्कोर दिखेगा वह कुल में 2 अंक का ही होगा।" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "समस्या सूची लोड हो रही है..." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "लिंग वितरण" - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "प्रशिक्षक डैशबोर्ड" @@ -14663,6 +14711,10 @@ msgstr "" msgid "Add CCX Coach" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "इस वक्त कोई डेटा दिखाने के लिए नहीं हैं।" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "" @@ -14711,6 +14763,10 @@ msgstr "" msgid "Download Problem Data for all Problems as a CSV" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr " श्रेणी वितरण प्रति समस्या" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "" @@ -14723,6 +14779,10 @@ msgstr "" msgid "This is a partial list, to view all students download as a csv." msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "इस भाग में कोई समस्याएं नहीं हैं।" + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "ई-मेल भेजें" @@ -15527,6 +15587,10 @@ msgstr "" msgid "Discount Applied:" msgstr "" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "छात्र" + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -15768,6 +15832,10 @@ msgstr "" msgid "Currently the {platform_name} servers are overloaded" msgstr "" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "" @@ -15871,16 +15939,26 @@ msgstr "आपका नाम बदलते समय ये त्रुट msgid "Re-Verify for {course_name}" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." msgstr "" +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" + #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." msgstr "" @@ -18814,10 +18892,6 @@ msgstr "" msgid "Current Library:" msgstr "" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "" diff --git a/conf/locale/hi/LC_MESSAGES/djangojs.mo b/conf/locale/hi/LC_MESSAGES/djangojs.mo index a8f72d1d46..a06afb60dd 100644 Binary files a/conf/locale/hi/LC_MESSAGES/djangojs.mo and b/conf/locale/hi/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/hi/LC_MESSAGES/djangojs.po b/conf/locale/hi/LC_MESSAGES/djangojs.po index 2656a395db..82fd2f2457 100644 --- a/conf/locale/hi/LC_MESSAGES/djangojs.po +++ b/conf/locale/hi/LC_MESSAGES/djangojs.po @@ -46,10 +46,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:31+0000\n" -"PO-Revision-Date: 2015-07-10 19:12+0000\n" +"POT-Creation-Date: 2015-07-22 17:43+0000\n" +"PO-Revision-Date: 2015-07-14 14:36+0000\n" "Last-Translator: Sarina Canelake \n" -"Language-Team: Hindi (http://www.transifex.com/p/edx-platform/language/hi/)\n" +"Language-Team: Hindi (http://www.transifex.com/projects/p/edx-platform/language/hi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2278,19 +2278,38 @@ msgstr "" msgid "Tags:" 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" msgstr "" +#: lms/djangoapps/teams/static/teams/js/collections/team.js +msgid "open_slots" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/collections/topic.js msgid "team count" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "" +msgstr[1] "" + +#: 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/teams.js +msgid "Create new team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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 @@ -2305,6 +2324,14 @@ msgstr "" msgid "Browse" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "" + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2357,22 +2384,6 @@ msgstr "ग्रेड बनाने मे कुछ गड़बड़। msgid "Error generating problem grade report. Please try again." msgstr "" -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "" - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3144,6 +3155,12 @@ msgstr "" msgid "An error occurred. Please try again later." msgstr "" +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "" +msgstr[1] "" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "" @@ -3157,13 +3174,29 @@ msgstr "" msgid "Focus grabber" msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3173,22 +3206,6 @@ msgstr "" msgid "Current tab" msgstr "" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "" @@ -4928,6 +4945,21 @@ msgstr "" msgid "remove" msgstr "" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "" @@ -5020,10 +5052,6 @@ msgstr "" msgid "LEARN MORE" msgstr "" -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "" - #: lms/templates/discovery/result_item.underscore msgid "Starts" msgstr "" @@ -5907,10 +5935,6 @@ msgstr "" msgid "Common Problem Types" msgstr "" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "" diff --git a/conf/locale/ko_KR/LC_MESSAGES/django.mo b/conf/locale/ko_KR/LC_MESSAGES/django.mo index ef42887f71..90920ed063 100644 Binary files a/conf/locale/ko_KR/LC_MESSAGES/django.mo and b/conf/locale/ko_KR/LC_MESSAGES/django.mo differ diff --git a/conf/locale/ko_KR/LC_MESSAGES/django.po b/conf/locale/ko_KR/LC_MESSAGES/django.po index 9381c1e8fb..047565aadf 100644 --- a/conf/locale/ko_KR/LC_MESSAGES/django.po +++ b/conf/locale/ko_KR/LC_MESSAGES/django.po @@ -19,6 +19,7 @@ # Translators: # bossnm11 , 2014 # mariana1201 , 2014 +# Hongseob Lee , 2015 # Jong-Dae Park , 2013 # jeon , 2014-2015 # Kevin Min , 2015 @@ -80,10 +81,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:33+0000\n" +"POT-Creation-Date: 2015-07-22 17:45+0000\n" "PO-Revision-Date: 2015-05-28 20:00+0000\n" "Last-Translator: Kevin Min \n" -"Language-Team: Korean (Korea) (http://www.transifex.com/p/edx-platform/language/ko_KR/)\n" +"Language-Team: Korean (Korea) (http://www.transifex.com/projects/p/edx-platform/language/ko_KR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -103,10 +104,10 @@ msgstr "" msgid "Discussion" msgstr "" -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html +#: cms/djangoapps/contentstore/views/component.py +#: lms/djangoapps/class_dashboard/dashboard_data.py msgid "Problem" -msgstr "문제" +msgstr "" #: cms/djangoapps/contentstore/views/component.py #: common/lib/xmodule/xmodule/video_module/video_module.py @@ -201,6 +202,69 @@ msgid "" " Please list each domain on its own line." msgstr "" +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html +msgid "Course" +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/annotatable_module.py +#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/combined_open_ended_module.py +#: common/lib/xmodule/xmodule/discussion_module.py +#: common/lib/xmodule/xmodule/html_module.py +#: common/lib/xmodule/xmodule/imageannotation_module.py +#: common/lib/xmodule/xmodule/library_content_module.py +#: common/lib/xmodule/xmodule/lti_module.py +#: common/lib/xmodule/xmodule/peer_grading_module.py +#: common/lib/xmodule/xmodule/split_test_module.py +#: common/lib/xmodule/xmodule/textannotation_module.py +#: common/lib/xmodule/xmodule/videoannotation_module.py +#: common/lib/xmodule/xmodule/word_cloud_module.py +#: cms/templates/container.html cms/templates/library.html +msgid "Display Name" +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "" @@ -561,8 +625,8 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" #: common/djangoapps/student/views.py @@ -1512,23 +1576,6 @@ msgstr "" msgid "XML data for the annotation" msgstr "" -#: common/lib/xmodule/xmodule/annotatable_module.py -#: common/lib/xmodule/xmodule/capa_base.py -#: common/lib/xmodule/xmodule/combined_open_ended_module.py -#: common/lib/xmodule/xmodule/discussion_module.py -#: common/lib/xmodule/xmodule/html_module.py -#: common/lib/xmodule/xmodule/imageannotation_module.py -#: common/lib/xmodule/xmodule/library_content_module.py -#: common/lib/xmodule/xmodule/lti_module.py -#: common/lib/xmodule/xmodule/peer_grading_module.py -#: common/lib/xmodule/xmodule/split_test_module.py -#: common/lib/xmodule/xmodule/textannotation_module.py -#: common/lib/xmodule/xmodule/videoannotation_module.py -#: common/lib/xmodule/xmodule/word_cloud_module.py -#: cms/templates/container.html cms/templates/library.html -msgid "Display Name" -msgstr "" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1647,9 +1694,8 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" #: common/lib/xmodule/xmodule/capa_base.py @@ -3016,10 +3062,6 @@ msgstr "" msgid "Library Version" msgstr "" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "" @@ -3580,10 +3622,11 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py @@ -4583,7 +4626,7 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" @@ -4698,6 +4741,34 @@ msgstr "" msgid "Visit a course wiki to add an article." msgstr "" +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" + #: lms/templates/courseware/courseware-error.html msgid "Courseware" msgstr "강좌물" @@ -5307,9 +5378,10 @@ msgstr "" msgid "Gender" msgstr "성(생물학적)" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html +#: lms/djangoapps/instructor/views/api.py +#: lms/djangoapps/instructor_task/tasks_helper.py msgid "Level of Education" -msgstr "교육 수준" +msgstr "" #: lms/templates/register.html msgid "Mailing Address" @@ -5326,28 +5398,22 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5403,29 +5469,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5479,28 +5544,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5630,12 +5695,12 @@ msgstr "" msgid "Data Download" msgstr "데이터 다운로드" -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Analytics" -msgstr "분석" +#: lms/djangoapps/instructor/views/instructor_dashboard.py +msgid "For analytics about your course, go to {analytics_dashboard_name}." +msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." +msgid "Analytics" msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py @@ -5906,7 +5971,6 @@ msgid "Title" msgstr "" #: lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "생년" @@ -6515,10 +6579,6 @@ msgstr "" msgid "University" msgstr "" -#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html -msgid "Course" -msgstr "" - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "" @@ -7220,6 +7280,10 @@ msgstr "" msgid "course_id must be provided" msgstr "" +#: lms/djangoapps/teams/views.py +msgid "The supplied topic id {topic_id} is not valid" +msgstr "" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "" @@ -7229,11 +7293,11 @@ msgid "last_activity is not yet supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The supplied course_id {course_id} is not valid." +msgid "The ordering {} is not supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The ordering {} is not supported" +msgid "The supplied course_id {course_id} is not valid." msgstr "" #: lms/djangoapps/teams/views.py @@ -7286,6 +7350,16 @@ msgstr "" msgid "There was an error verifying your ID photos." msgstr "" +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "" @@ -8076,6 +8150,10 @@ msgstr "" msgid "A cohort with the same name already exists." msgstr "" +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -8123,6 +8201,20 @@ msgid "" "credit provider." msgstr "" +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "" @@ -8709,9 +8801,7 @@ msgstr "" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -8847,6 +8937,11 @@ msgstr "" msgid "Course Navigation" msgstr "강좌 찾아가기" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py msgid "Help" @@ -9007,7 +9102,8 @@ msgstr "" msgid "Starts" msgstr "" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "상황판" @@ -9036,11 +9132,11 @@ msgid "Clear search" msgstr "" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" +msgid "Find New Courses" msgstr "" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." +msgid "Account Status Info" msgstr "" #: lms/templates/dashboard.html @@ -9631,12 +9727,7 @@ msgid "More options dropdown" msgstr "추가 옵션 드롭다운" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" +msgid "Profile" msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html @@ -9644,14 +9735,15 @@ msgstr "" msgid "Shopping Cart" msgstr "" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" -msgstr "등록" - #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "Sign in" msgstr "" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +#: lms/templates/register.html +msgid "Register" +msgstr "등록" + #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "" "Warning: Your browser is not fully supported. We strongly " @@ -9671,10 +9763,6 @@ msgstr "" msgid "Schools" msgstr "학교" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "지금 등록하세요" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -10687,6 +10775,11 @@ msgstr "" msgid "I completed the {course_title} course on {platform_name}." msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "" @@ -10695,6 +10788,15 @@ msgstr "" msgid "Post on Facebook" msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "" @@ -10935,6 +11037,10 @@ msgstr "{chapter}, 현재 장" msgid "due {date}" msgstr "마감일 {date}" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "" + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -11034,10 +11140,6 @@ msgstr "수업 종료" msgid "Estimated Effort" msgstr "예상되는 노력" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Prerequisites" msgstr "선수요건" @@ -11066,12 +11168,24 @@ msgstr "" msgid "View this course as:" msgstr "" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" +msgid "Username or email:" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." msgstr "" #: lms/templates/courseware/course_navigation.html @@ -11106,6 +11220,10 @@ msgstr "" msgid "{platform_name} Logo" msgstr "" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "" @@ -11369,74 +11487,6 @@ msgstr "" msgid "To send email, visit the Email section of the Instructor Dashboard." msgstr "" -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "현재 분석내용이 사용가능 하지 않습니다. " - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "일별 학생 활동" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "일" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "학생" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "최대" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "획득한 포인트(학생 수)" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "정답을 맞춘 학생들" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "학생수" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "유보중인 강사 업무" @@ -11603,11 +11653,12 @@ msgid "Requirements for Course Credit" msgstr "" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." +msgid "{student_name}, you are no longer eligible for credit in this course." msgstr "" #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." +msgid "" +"{student_name}, you have met the requirements for credit in this course." msgstr "" #: lms/templates/courseware/progress.html @@ -11672,6 +11723,46 @@ msgid "" "another section on the left." msgstr "최근에 {section_link}에 있었습니다. 할일을 완료했다면, 왼쪽에서 다른 섹션을 선택하세요." +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "" + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -11787,10 +11878,6 @@ msgstr "" msgid "I'm learning on {platform_name}:" msgstr "" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "" @@ -12676,11 +12763,6 @@ msgstr "" msgid "You have been invited to a beta test for {course_name}" msgstr "" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "" - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "" @@ -14085,30 +14167,6 @@ msgstr "" msgid "Send me a copy of the invoice" msgstr "" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "문제 목록 로딩 ..." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "성별 분포" - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "강사 상황판" @@ -14327,6 +14385,10 @@ msgstr "" msgid "Add CCX Coach" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "" @@ -14375,6 +14437,10 @@ msgstr "" msgid "Download Problem Data for all Problems as a CSV" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "" @@ -14387,6 +14453,10 @@ msgstr "" msgid "This is a partial list, to view all students download as a csv." msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "" @@ -15148,6 +15218,10 @@ msgstr "" msgid "Discount Applied:" msgstr "" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "학생" + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -15384,6 +15458,10 @@ msgstr "" msgid "Currently the {platform_name} servers are overloaded" msgstr "" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "" @@ -15487,16 +15565,26 @@ msgstr "" msgid "Re-Verify for {course_name}" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." msgstr "" +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" + #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." msgstr "" @@ -18428,10 +18516,6 @@ msgstr "" msgid "Current Library:" msgstr "" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "" diff --git a/conf/locale/ko_KR/LC_MESSAGES/djangojs.mo b/conf/locale/ko_KR/LC_MESSAGES/djangojs.mo index 41c9b9f315..e22e0a6d94 100644 Binary files a/conf/locale/ko_KR/LC_MESSAGES/djangojs.mo and b/conf/locale/ko_KR/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/ko_KR/LC_MESSAGES/djangojs.po b/conf/locale/ko_KR/LC_MESSAGES/djangojs.po index 94c8d5b591..d17b382cfb 100644 --- a/conf/locale/ko_KR/LC_MESSAGES/djangojs.po +++ b/conf/locale/ko_KR/LC_MESSAGES/djangojs.po @@ -9,6 +9,7 @@ # jeon , 2014-2015 # Jong-Dae Park , 2013 # Kevin Min , 2015 +# Rang Kim , 2015 # #-#-#-#-# djangojs-studio.po (edx-platform) #-#-#-#-# # edX translation file. # Copyright (C) 2015 EdX @@ -21,6 +22,7 @@ # jeon , 2014-2015 # Chanseok , 2014 # seungil , 2014 +# SANG WOO KIM , 2015 # #-#-#-#-# underscore.po (edx-platform) #-#-#-#-# # edX translation file # Copyright (C) 2015 edX @@ -47,10 +49,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:31+0000\n" -"PO-Revision-Date: 2015-07-10 19:12+0000\n" +"POT-Creation-Date: 2015-07-22 17:43+0000\n" +"PO-Revision-Date: 2015-07-14 14:36+0000\n" "Last-Translator: Sarina Canelake \n" -"Language-Team: Korean (Korea) (http://www.transifex.com/p/edx-platform/language/ko_KR/)\n" +"Language-Team: Korean (Korea) (http://www.transifex.com/projects/p/edx-platform/language/ko_KR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2222,14 +2224,31 @@ msgstr "" msgid "name" msgstr "이름" +#: lms/djangoapps/teams/static/teams/js/collections/team.js +msgid "open_slots" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/collections/topic.js msgid "team count" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "" + +#: 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/teams.js +msgid "Create new team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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 @@ -2244,6 +2263,14 @@ msgstr "" msgid "Browse" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "" + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2294,22 +2321,6 @@ msgstr "" msgid "Error generating problem grade report. Please try again." msgstr "" -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "" - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3052,6 +3063,11 @@ msgstr "" msgid "An error occurred. Please try again later." msgstr "" +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "" @@ -3064,13 +3080,29 @@ msgstr "오류가 있습니다. 다시 검색해 보십시요." msgid "Focus grabber" msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3080,22 +3112,6 @@ msgstr "" msgid "Current tab" msgstr "" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "" @@ -4802,6 +4818,21 @@ msgstr "" msgid "remove" msgstr "" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "" @@ -4894,10 +4925,6 @@ msgstr "" msgid "LEARN MORE" msgstr "" -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "" - #: lms/templates/discovery/result_item.underscore msgid "Starts" msgstr "" @@ -5779,10 +5806,6 @@ msgstr "" msgid "Common Problem Types" msgstr "" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "" diff --git a/conf/locale/pt_BR/LC_MESSAGES/django.mo b/conf/locale/pt_BR/LC_MESSAGES/django.mo index bac899477b..57a2623a9f 100644 Binary files a/conf/locale/pt_BR/LC_MESSAGES/django.mo and b/conf/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/conf/locale/pt_BR/LC_MESSAGES/django.po b/conf/locale/pt_BR/LC_MESSAGES/django.po index 2c8c19189e..3a7215a00b 100644 --- a/conf/locale/pt_BR/LC_MESSAGES/django.po +++ b/conf/locale/pt_BR/LC_MESSAGES/django.po @@ -30,7 +30,7 @@ # Kevin Grist , 2014 # Larissa Queiroz Pontes , 2015 # Leonardo Flores Zambaldi , 2014 -# Leonardo Lehnemann Agostinho Martins , 2014 +# Leonardo Lehnemann Agostinho Martins , 2014-2015 # LucasPPires , 2014 # LucasPPires , 2014 # lukassem , 2014 @@ -221,10 +221,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:33+0000\n" -"PO-Revision-Date: 2015-06-29 04:46+0000\n" +"POT-Creation-Date: 2015-07-22 17:45+0000\n" +"PO-Revision-Date: 2015-07-20 00:15+0000\n" "Last-Translator: javiercencig \n" -"Language-Team: Portuguese (Brazil) (http://www.transifex.com/p/edx-platform/language/pt_BR/)\n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/edx-platform/language/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -242,8 +242,6 @@ msgstr "Discussão" #: cms/djangoapps/contentstore/views/component.py #: lms/djangoapps/class_dashboard/dashboard_data.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Problem" msgstr "Problema" @@ -343,6 +341,68 @@ msgid "" " Please list each domain on its own line." msgstr "" +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py +msgid "Course" +msgstr "Curso" + +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/annotatable_module.py +#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/combined_open_ended_module.py +#: common/lib/xmodule/xmodule/discussion_module.py +#: common/lib/xmodule/xmodule/html_module.py +#: common/lib/xmodule/xmodule/imageannotation_module.py +#: common/lib/xmodule/xmodule/library_content_module.py +#: common/lib/xmodule/xmodule/lti_module.py +#: common/lib/xmodule/xmodule/peer_grading_module.py +#: common/lib/xmodule/xmodule/split_test_module.py +#: common/lib/xmodule/xmodule/textannotation_module.py +#: common/lib/xmodule/xmodule/videoannotation_module.py +#: common/lib/xmodule/xmodule/word_cloud_module.py +msgid "Display Name" +msgstr "Nome de exibição" + +#: common/djangoapps/course_modes/models.py +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "Certificado do Código de Honra" @@ -701,8 +761,8 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" #: common/djangoapps/student/views.py @@ -1701,22 +1761,6 @@ msgstr "Não foi possível interpretar '{given_answer}' como um número." msgid "XML data for the annotation" msgstr "Dados XML para a anotação" -#: common/lib/xmodule/xmodule/annotatable_module.py -#: common/lib/xmodule/xmodule/capa_base.py -#: common/lib/xmodule/xmodule/combined_open_ended_module.py -#: common/lib/xmodule/xmodule/discussion_module.py -#: common/lib/xmodule/xmodule/html_module.py -#: common/lib/xmodule/xmodule/imageannotation_module.py -#: common/lib/xmodule/xmodule/library_content_module.py -#: common/lib/xmodule/xmodule/lti_module.py -#: common/lib/xmodule/xmodule/peer_grading_module.py -#: common/lib/xmodule/xmodule/split_test_module.py -#: common/lib/xmodule/xmodule/textannotation_module.py -#: common/lib/xmodule/xmodule/videoannotation_module.py -#: common/lib/xmodule/xmodule/word_cloud_module.py -msgid "Display Name" -msgstr "Nome de exibição" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1841,14 +1885,9 @@ msgstr "Ordenamento aleatório" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" -"Define com que frequência as entradas são organizadas aleatoriamente quando " -"um aluno carrega o problema. Esta definição aplica-se apenas aos problemas " -"que podem ter gerado aleatoriamente valores numéricos. Um valor definido por" -" padrão pode ser definido nas configurações avançadas." #: common/lib/xmodule/xmodule/capa_base.py msgid "On Reset" @@ -3314,10 +3353,6 @@ msgstr "" msgid "Library Version" msgstr "" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "" @@ -3930,10 +3965,11 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py @@ -4993,7 +5029,7 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" @@ -5109,6 +5145,34 @@ msgstr "" msgid "Visit a course wiki to add an article." msgstr "Visite uma wiki do curso para adicionar um artigo." +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" + #: lms/djangoapps/courseware/tabs.py #: lms/templates/courseware/courseware-error.html msgid "Courseware" @@ -5756,7 +5820,6 @@ msgstr "Sexo" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/tasks_helper.py -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Level of Education" msgstr "Nível educacional" @@ -5776,28 +5839,22 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5856,29 +5913,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5932,40 +5988,29 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" -"Seu relatório de avaliação está sendo gerado! Você pode visualizar o status " -"da tarefa de geração na seção \"Tarefas pendentes\". " #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" -"Uma tarefa de geração de relatório de avaliação já está em progresso. " -"Verifique a tabela \"Tarefas pendentes\" para visualizar o status da tarefa." -" Quando finalizado, o relatório está disponível para download na tabela " -"abaixo." #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" -"Seu relatório de avaliação do problema está sendo gerado! Você pode " -"visualizar o status da tarefa de geração na seção \"Tarefas pendentes\"." #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" -"Um relatório de avaliação do problema já está sendo gerado. Verifique a " -"tabela \"Tarefas pendentes\" para visualizar o status da tarefa. Quando " -"finalizado, o relatório está disponível para download na tabela abaixo." #: lms/djangoapps/instructor/views/api.py msgid "Successfully changed due date for student {0} for {1} to {2}" @@ -6099,13 +6144,12 @@ msgid "Data Download" msgstr "Download de dados" #: lms/djangoapps/instructor/views/instructor_dashboard.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Analytics" -msgstr "Estatísticas" +msgid "For analytics about your course, go to {analytics_dashboard_name}." +msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." -msgstr "" +msgid "Analytics" +msgstr "Estatísticas" #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Metrics" @@ -6380,7 +6424,6 @@ msgid "Title" msgstr "Título" #: lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "Ano de nascimento" @@ -7016,10 +7059,6 @@ msgstr "Comentários" msgid "University" msgstr "Universidade" -#: lms/djangoapps/shoppingcart/reports.py -msgid "Course" -msgstr "Curso" - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "Data de anúncio do curso" @@ -7783,6 +7822,10 @@ msgstr "" msgid "course_id must be provided" msgstr "" +#: lms/djangoapps/teams/views.py +msgid "The supplied topic id {topic_id} is not valid" +msgstr "" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "" @@ -7792,11 +7835,11 @@ msgid "last_activity is not yet supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The supplied course_id {course_id} is not valid." +msgid "The ordering {} is not supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The ordering {} is not supported" +msgid "The supplied course_id {course_id} is not valid." msgstr "" #: lms/djangoapps/teams/views.py @@ -7853,6 +7896,16 @@ msgstr "" msgid "There was an error verifying your ID photos." msgstr "Ocorreu um erro ao verificar as suas fotos de identificação." +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "" @@ -8689,6 +8742,10 @@ msgstr "" msgid "A cohort with the same name already exists." msgstr "" +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -8736,6 +8793,20 @@ msgid "" "credit provider." msgstr "" +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "" @@ -9335,9 +9406,7 @@ msgstr "Página não encontrada" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -9474,6 +9543,11 @@ msgstr "" msgid "Course Navigation" msgstr "Navegação do curso" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py msgid "Help" @@ -9634,7 +9708,8 @@ msgstr "" msgid "Starts" msgstr "" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "Painel de controle" @@ -9663,11 +9738,11 @@ msgid "Clear search" msgstr "" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" +msgid "Find New Courses" msgstr "" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." +msgid "Account Status Info" msgstr "" #: lms/templates/dashboard.html @@ -10283,12 +10358,7 @@ msgid "More options dropdown" msgstr "Mais opções no menu suspenso" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" +msgid "Profile" msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html @@ -10296,14 +10366,15 @@ msgstr "" msgid "Shopping Cart" msgstr "Carrinho de compras" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" -msgstr "Registre-se" - #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "Sign in" msgstr "" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +#: lms/templates/register.html +msgid "Register" +msgstr "Registre-se" + #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "" "Warning: Your browser is not fully supported. We strongly " @@ -10323,10 +10394,6 @@ msgstr "" msgid "Schools" msgstr "Escolas" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "Registre-se agora" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -11392,6 +11459,11 @@ msgstr "" msgid "I completed the {course_title} course on {platform_name}." msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "" @@ -11400,6 +11472,15 @@ msgstr "" msgid "Post on Facebook" msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "" @@ -11653,6 +11734,10 @@ msgstr "{chapter}, capítulo atual" msgid "due {date}" msgstr "data de entrega {date}" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "" + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -11759,10 +11844,6 @@ msgstr "Término das aulas" msgid "Estimated Effort" msgstr "Dedicação estimada" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Prerequisites" msgstr "Pré-requisitos " @@ -11791,12 +11872,24 @@ msgstr "" msgid "View this course as:" msgstr "" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" +msgid "Username or email:" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." msgstr "" #: lms/templates/courseware/course_navigation.html @@ -11831,6 +11924,10 @@ msgstr "" msgid "{platform_name} Logo" msgstr "" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "" @@ -12114,76 +12211,6 @@ msgstr "" "Para mandar um e-mail, visite a seção de Emails no Painel de controle do " "instrutor. " -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "Não há estatísticas disponíveis no momento." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "Atividades dos alunos por dia" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "Dia" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "Alunos" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "Distribuição de pontuações para os problemas" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "Máximo" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "Pontos obtidos (número de alunos)" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "Não há dados disponíveis para exibição no momento." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "" -"Carregando os gráficos mais recentes para você, dependendo do tamanho da sua" -" turma isto pode levar alguns minutos." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "Contagem de alunos que abriram uma subseção" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr "Distribuição de notas por problema" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "Não há problemas nesta seção." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "Alunos que responderam corretamente" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "Número de alunos" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "Tarefas pendentes do instrutor" @@ -12352,11 +12379,12 @@ msgid "Requirements for Course Credit" msgstr "" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." +msgid "{student_name}, you are no longer eligible for credit in this course." msgstr "" #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." +msgid "" +"{student_name}, you have met the requirements for credit in this course." msgstr "" #: lms/templates/courseware/progress.html @@ -12423,6 +12451,46 @@ msgstr "" "Recentemente você acessou a seção {section_link}. Caso já tenha concluído, " "escolha outra seção à esquerda." +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "" + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -12557,10 +12625,6 @@ msgstr "" msgid "I'm learning on {platform_name}:" msgstr "" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "" @@ -13475,11 +13539,6 @@ msgstr "" msgid "You have been invited to a beta test for {course_name}" msgstr "Você foi convidado para um teste beta do curso {course_name}" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "" - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "" @@ -14982,34 +15041,6 @@ msgstr "" msgid "Send me a copy of the invoice" msgstr "" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "Distribuição de pontuação" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "" -"O gráfico abaixo mostra a distribuição da pontuação para cada problema-" -"padrão em sua classe, especificada pelo nome do URL do problema." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "" -"As pontuações são mostradas sem ponderação de peso, então se o seu problema " -"contém 2 questões, será mostrado com um total de 2 pontos." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "Carregando a lista de problemas..." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "Distribuição de gênero" - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "Painel de controle do instrutor" @@ -15232,6 +15263,10 @@ msgstr "" msgid "Add CCX Coach" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "Não há dados disponíveis para exibição no momento." + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "Utilize a opção Recarregar gráficos para atualizar os gráficos." @@ -15283,6 +15318,10 @@ msgstr "" msgid "Download Problem Data for all Problems as a CSV" msgstr "Baixar dados dos problemas para todos os problemas em um arquivo CSV" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr "Distribuição de notas por problema" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "Baixar aluno aberto como CSV" @@ -15295,6 +15334,10 @@ msgstr "Baixe as notas dos alunos como arquivo CSV" msgid "This is a partial list, to view all students download as a csv." msgstr "Esta é uma lista parcial, para ver todos os alunos baixe como csv." +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "Não há problemas nesta seção." + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "Enviar e-mail" @@ -16120,6 +16163,10 @@ msgstr "" msgid "Discount Applied:" msgstr "" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "Alunos" + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -16365,6 +16412,10 @@ msgstr "" msgid "Currently the {platform_name} servers are overloaded" msgstr "No momento, os servidores do {platform_name} estão sobrecarregados" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "" @@ -16472,16 +16523,26 @@ msgstr "O seguinte erro ocorreu ao editar o seu nome: " msgid "Re-Verify for {course_name}" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." msgstr "" +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" + #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." msgstr "Atualize sua matrícula do {course_name}." @@ -19442,10 +19503,6 @@ msgstr "" msgid "Current Library:" msgstr "" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "" diff --git a/conf/locale/pt_BR/LC_MESSAGES/djangojs.mo b/conf/locale/pt_BR/LC_MESSAGES/djangojs.mo index e9465a965e..5679cbf8bd 100644 Binary files a/conf/locale/pt_BR/LC_MESSAGES/djangojs.mo and b/conf/locale/pt_BR/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/pt_BR/LC_MESSAGES/djangojs.po b/conf/locale/pt_BR/LC_MESSAGES/djangojs.po index e8a94341e3..5e1133950c 100644 --- a/conf/locale/pt_BR/LC_MESSAGES/djangojs.po +++ b/conf/locale/pt_BR/LC_MESSAGES/djangojs.po @@ -104,7 +104,7 @@ # Bruno Sette , 2015 # Cleomir Waiczyk , 2015 # Edgar Aparecido Pereira de Melo , 2014 -# Felipe Lube de Bragança , 2015 +# Felipe Lube de Bragança , 2015 # Fernando Nunes , 2015 # Francisco Cantarutti , 2014 # Francisco de Assis Ventura Filho , 2015 @@ -116,6 +116,7 @@ # Lulatini , 2015 # Maurício Gonçalves Melara Camargo , 2015 # Andrew Melim , 2015 +# sgtmarciosilva , 2015 # Thiago Perrotta , 2014 # Victor Hochgreb de Freitas , 2015 # Victor Hochgreb de Freitas , 2015 @@ -147,10 +148,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:31+0000\n" -"PO-Revision-Date: 2015-07-13 01:26+0000\n" -"Last-Translator: Renata Barboza-Murray\n" -"Language-Team: Portuguese (Brazil) (http://www.transifex.com/p/edx-platform/language/pt_BR/)\n" +"POT-Creation-Date: 2015-07-22 17:43+0000\n" +"PO-Revision-Date: 2015-07-20 00:03+0000\n" +"Last-Translator: Sarina Canelake \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/edx-platform/language/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2341,19 +2342,38 @@ msgstr "Responder" msgid "Tags:" msgstr "Marcações:" +#: 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" msgstr "" +#: lms/djangoapps/teams/static/teams/js/collections/team.js +msgid "open_slots" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/collections/topic.js msgid "team count" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "" +msgstr[1] "" + +#: 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/teams.js +msgid "Create new team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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 @@ -2368,6 +2388,14 @@ msgstr "" msgid "Browse" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "" + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2420,22 +2448,6 @@ msgstr "Erro ao gerar notas. Por favor, tente novamente." msgid "Error generating problem grade report. Please try again." msgstr "" -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "Painel de indicadores indisponível." - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "Erro ao recuperar as distribuições de notas." - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "Última atualização: <%= timestamp %>" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "<%= num_students %> alunos avaliados." - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3248,6 +3260,12 @@ msgstr "Sua doação não pôde ser enviada." msgid "An error occurred. Please try again later." msgstr "Ocorreu um erro. Por favor, tente novamente mais tarde." +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "" +msgstr[1] "" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "Não foi possível encontrar resultados para \"%s\"." @@ -3260,8 +3278,8 @@ msgstr "Ocorreu um erro, tente realizar a busca novamente." msgid "Focus grabber" msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." @@ -3269,6 +3287,22 @@ msgstr "" "Ocorreu um erro. Certifique-se de que você está conectado à internet e, em " "seguida, tente atualizar a página." +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "Ocultar anotações " + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "Visualizar anotações" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "Exibir anotações" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "Ocultar anotações" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3278,22 +3312,6 @@ msgstr "Insira um termo no %(anchor_start)s campo de busca%(anchor_end)s." msgid "Current tab" msgstr "Aba atual" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "Ocultar anotações " - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "Visualizar anotações" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "Exibir anotações" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "Ocultar anotações" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "Localização no curso" @@ -5044,6 +5062,21 @@ msgstr "" msgid "remove" msgstr "" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "" @@ -5136,10 +5169,6 @@ msgstr "" msgid "LEARN MORE" msgstr "" -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "" - #: lms/templates/discovery/result_item.underscore msgid "Starts" msgstr "" @@ -6023,10 +6052,6 @@ msgstr "" msgid "Common Problem Types" msgstr "" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "" diff --git a/conf/locale/rtl/LC_MESSAGES/django.mo b/conf/locale/rtl/LC_MESSAGES/django.mo index b19bae8dca..61dd2153d0 100644 Binary files a/conf/locale/rtl/LC_MESSAGES/django.mo and b/conf/locale/rtl/LC_MESSAGES/django.mo differ diff --git a/conf/locale/rtl/LC_MESSAGES/django.po b/conf/locale/rtl/LC_MESSAGES/django.po index 8b1600785c..7d562b35c0 100644 --- a/conf/locale/rtl/LC_MESSAGES/django.po +++ b/conf/locale/rtl/LC_MESSAGES/django.po @@ -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-07-13 04:42+0000\n" -"PO-Revision-Date: 2015-07-13 04:42:08.333956\n" +"POT-Creation-Date: 2015-07-22 18:12+0000\n" +"PO-Revision-Date: 2015-07-22 18:12:54.680330\n" "Last-Translator: \n" "Language-Team: openedx-translation \n" "MIME-Version: 1.0\n" @@ -62,8 +62,6 @@ msgstr "يهسذعسسهخر" #: cms/djangoapps/contentstore/views/component.py #: lms/djangoapps/class_dashboard/dashboard_data.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Problem" msgstr "حقخزمثو" @@ -167,6 +165,78 @@ msgstr "" "مهسف خب يخوشهرس فاشف شقث شممخصثي فخ وشنث ذقخسس-يخوشهر قثضعثسفس فخ فاهس سهفث." " حمثشسث مهسف ثشذا يخوشهر خر هفس خصر مهرث." +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "وخيث" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "دثقهبهذشفهخر يثشيمهرث" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" +"خحفهخرشم: شبفثق فاهس يشفث/فهوث, عسثقس صهمم رخ مخرلثق زث شزمث فخ سعزوهف " +"حاخفخس بخق دثقهبهذشفهخر. فاهس شححهثس خرمغ فخ وخيثس فاشف قثضعهقث " +"دثقهبهذشفهخر." + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html +msgid "Course" +msgstr "ذخعقسث" + +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/annotatable_module.py +#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/combined_open_ended_module.py +#: common/lib/xmodule/xmodule/discussion_module.py +#: common/lib/xmodule/xmodule/html_module.py +#: common/lib/xmodule/xmodule/imageannotation_module.py +#: common/lib/xmodule/xmodule/library_content_module.py +#: common/lib/xmodule/xmodule/lti_module.py +#: common/lib/xmodule/xmodule/peer_grading_module.py +#: common/lib/xmodule/xmodule/split_test_module.py +#: common/lib/xmodule/xmodule/textannotation_module.py +#: common/lib/xmodule/xmodule/videoannotation_module.py +#: common/lib/xmodule/xmodule/word_cloud_module.py +#: cms/templates/container.html cms/templates/library.html +msgid "Display Name" +msgstr "يهسحمشغ رشوث" + +#: common/djangoapps/course_modes/models.py +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "حقهذث" + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "عحلقشيث يثشيمهرث" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" +"خحفهخرشم: شبفثق فاهس يشفث/فهوث, عسثقس صهمم رخ مخرلثق زث شزمث فخ ثرقخمم هر " +"فاهس وخيث. مثشدث فاهس زمشرن هب عسثقس ذشر ثرقخمم هر فاهس وخيث عرفهم " +"ثرقخمموثرف ذمخسثس بخق فاث ذخعقسث." + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" +"خحفهخرشم: فاهس هس فاث سنع (سفخذن نثثحهرل عرهف) خب فاهس وخيث هر فاث ثطفثقرشم " +"ثذخووثقذث سثقدهذث. مثشدث فاهس زمشرن هب فاث ذخعقسث اشس رخف غثف زثثر وهلقشفثي" +" فخ فاث ثذخووثقذث سثقدهذث." + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "اخرخق ذخيث ذثقفهبهذشفث" @@ -545,11 +615,11 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" -"هب غخع يخر'ف اشدث شر {platform_name} شذذخعرف غثف, ذمهذن قثلهسفثق " -"رخص شف فاث فخح خب فاث حشلث." +"هب غخع يخر'ف اشدث شر {platform_name} شذذخعرف غثف, ذمهذن " +"قثلهسفثق شف فاث فخح خب فاث حشلث." #: common/djangoapps/student/views.py msgid "There was an error receiving your login information. Please email us." @@ -1545,23 +1615,6 @@ msgstr "ذخعمي رخف هرفثقحقثف '{given_answer}' شس ش رعوزث msgid "XML data for the annotation" msgstr "طوم يشفش بخق فاث شررخفشفهخر" -#: common/lib/xmodule/xmodule/annotatable_module.py -#: common/lib/xmodule/xmodule/capa_base.py -#: common/lib/xmodule/xmodule/combined_open_ended_module.py -#: common/lib/xmodule/xmodule/discussion_module.py -#: common/lib/xmodule/xmodule/html_module.py -#: common/lib/xmodule/xmodule/imageannotation_module.py -#: common/lib/xmodule/xmodule/library_content_module.py -#: common/lib/xmodule/xmodule/lti_module.py -#: common/lib/xmodule/xmodule/peer_grading_module.py -#: common/lib/xmodule/xmodule/split_test_module.py -#: common/lib/xmodule/xmodule/textannotation_module.py -#: common/lib/xmodule/xmodule/videoannotation_module.py -#: common/lib/xmodule/xmodule/word_cloud_module.py -#: cms/templates/container.html cms/templates/library.html -msgid "Display Name" -msgstr "يهسحمشغ رشوث" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1687,13 +1740,11 @@ msgstr "قشريخوهظشفهخر" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" -"يثبهرثس اخص خبفثر هرحعفس شقث قشريخوهظثي صاثر ش سفعيثرف مخشيس فاث حقخزمثو. " -"فاهس سثففهرل خرمغ شححمهثس فخ حقخزمثوس فاشف ذشر اشدث قشريخومغ لثرثقشفثي " -"رعوثقهذ دشمعثس. ش يثبشعمف دشمعث ذشر زث سثف هر شيدشرذثي سثففهرلس." +"يثبهرثس صاثر فخ قشريخوهظث فاث دشقهشزمثس سحثذهبهثي هر فاث شسسخذهشفثي حغفاخر " +"سذقهحف. بخق حقخزمثوس فاشف يخ رخف قشريخوهظث دشمعثس, سحثذهبغ \"رثدثق\". " #: common/lib/xmodule/xmodule/capa_base.py msgid "On Reset" @@ -3264,10 +3315,6 @@ msgstr "سثمثذف فاث مهزقشقغ بقخو صاهذا غخع صشرف msgid "Library Version" msgstr "مهزقشقغ دثقسهخر" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "وخيث" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "يثفثقوهرثس اخص ذخرفثرف هس يقشصر بقخو فاث مهزقشقغ" @@ -3911,15 +3958,17 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" -"سحثذهبغ اخص خبفثر دشقهشزمث دشمعثس هر ش حقخزمثو شقث قشريخوهظثي صاثر ش سفعيثرف" -" مخشيس فاث حقخزمثو. دشمهي دشمعثس شقث \"شمصشغس\", \"خرقثسثف\", \"رثدثق\", شري" -" \"حثق_سفعيثرف\". فاهس سثففهرل خرمغ شححمهثس فخ حقخزمثوس فاشف اشدث قشريخومغ " -"لثرثقشفثي رعوثقهذ دشمعثس." +"سحثذهبغ فاث يثبشعمف بخق اخص خبفثر دشقهشزمث دشمعثس هر ش حقخزمثو شقث " +"قشريخوهظثي. فاهس سثففهرل ساخعمي زث سثف فخ \"رثدثق\" عرمثسس غخع حمشر فخ " +"حقخدهيث ش حغفاخر سذقهحف فخ هيثرفهبغ شري قشريخوهظث دشمعثس هر وخسف خب فاث " +"حقخزمثوس هر غخعق ذخعقسث. دشمهي دشمعثس شقث \"شمصشغس\", \"خرقثسثف\", " +"\"رثدثق\", شري \"حثق_سفعيثرف\"." #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "Days Early for Beta Users" @@ -5064,7 +5113,7 @@ msgstr "ذثقفهبهذشفث دشمهيشفهخر" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" @@ -5188,6 +5237,38 @@ msgstr "صثمذخوث فخ فاث {platform_name} صهنه" msgid "Visit a course wiki to add an article." msgstr "دهسهف ش ذخعقسث صهنه فخ شيي شر شقفهذمث." +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "ذخعقسث يخثس رخف سفشقف عرفهم {}" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "غخع اشدث عربعمبهممثي وهمثسفخرثس" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "غخع يخ رخف اشدث شذذثسس فخ فاهس ذخعقسث" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "غخع يخ رخف اشدث شذذثسس فخ فاهس ذخعقسث خر ش وخزهمث يثدهذث" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" +"فاثقث هس رخ عسثق صهفا فاث عسثقرشوث خق ثوشهم شييقثسس {user_name} ثرقخممثي هر " +"فاهس ذخعقسث." + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" +"فاهس فغحث خب ذخوحخرثرف ذشررخف زث ساخصر صاهمث دهثصهرل فاث ذخعقسث شس ش " +"سحثذهبهذ سفعيثرف." + #: lms/djangoapps/courseware/tabs.py #: lms/templates/courseware/courseware-error.html msgid "Courseware" @@ -5845,7 +5926,6 @@ msgstr "لثريثق" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/tasks_helper.py -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Level of Education" msgstr "مثدثم خب ثيعذشفهخر" @@ -5865,39 +5945,31 @@ msgstr "ذخاخقف" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" -"غخعق ثرقخممثي سفعيثرف حقخبهمث قثحخقف هس زثهرل لثرثقشفثي! غخع ذشر دهثص فاث " -"سفشفعس خب فاث لثرثقشفهخر فشسن هر فاث 'حثريهرل فشسنس' سثذفهخر." +"فاث ثرقخممثي مثشقرثق حقخبهمث قثحخقف هس زثهرل ذقثشفثي. فخ دهثص فاث سفشفعس خب " +"فاث قثحخقف, سثث حثريهرل هرسفقعذفخق فشسنس زثمخص." #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" -"شر ثرقخممثي سفعيثرف حقخبهمث قثحخقف لثرثقشفهخر فشسن هس شمقثشيغ هر حقخلقثسس. " -"ذاثذن فاث 'حثريهرل فشسنس' فشزمث بخق فاث سفشفعس خب فاث فشسن. صاثر ذخوحمثفثي, " -"فاث قثحخقف صهمم زث شدشهمشزمث بخق يخصرمخشي هر فاث فشزمث زثمخص." +"فاهس ثرقخمموثرف قثحخقف هس ذعققثرفمغ زثهرل ذقثشفثي. فخ دهثص فاث سفشفعس خب فاث" +" قثحخقف, سثث حثريهرل هرسفقعذفخق فشسنس زثمخص. غخع صهمم زث شزمث فخ يخصرمخشي " +"فاث قثحخقف صاثر هف هس ذخوحمثفث." #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" -"غخعق سفعيثرفس صاخ وشغ ثرقخمم قثحخقف هس زثهرل لثرثقشفثي! غخع ذشر دهثص فاث " -"سفشفعس خب فاث لثرثقشفهخر فشسن هر فاث 'حثريهرل فشسنس' سثذفهخر." - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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 "The file must contain a 'cohort' column containing cohort names." @@ -5956,41 +6028,39 @@ msgstr "فخفشم يهسذخعرفثي شوخعرف" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" -"غخعق يثفشهمثي ثرقخمموثرف قثحخقف هس زثهرل لثرثقشفثي! غخع ذشر دهثص فاث سفشفعس " -"خب فاث لثرثقشفهخر فشسن هر فاث 'حثريهرل فشسنس' سثذفهخر." +"فاث يثفشهمثي ثرقخمموثرف قثحخقف هس زثهرل ذقثشفثي. فخ دهثص فاث سفشفعس خب فاث " +"قثحخقف, سثث حثريهرل هرسفقعذفخق فشسنس زثمخص." #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" -"ش يثفشهمثي ثرقخمموثرف قثحخقف لثرثقشفهخر فشسن هس شمقثشيغ هر حقخلقثسس. ذاثذن " -"فاث 'حثريهرل فشسنس' فشزمث بخق فاث سفشفعس خب فاث فشسن. صاثر ذخوحمثفثي, فاث " -"قثحخقف صهمم زث شدشهمشزمث بخق يخصرمخشي هر فاث فشزمث زثمخص." +"فاث يثفشهمثي ثرقخمموثرف قثحخقف هس زثهرل ذقثشفثي. فخ دهثص فاث سفشفعس خب فاث " +"قثحخقف, سثث حثريهرل هرسفقعذفخق فشسنس زثمخص. غخع صهمم زث شزمث فخ يخصرمخشي فاث" +" قثحخقف صاثر هف هس ذخوحمثفث." #: lms/djangoapps/instructor/views/api.py msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" -"غخعق ثطثذعفهدث سعووشقغ قثحخقف هس زثهرل ذقثشفثي. فخ دهثص فاث سفشفعس خب فاث " -"قثحخقف, سثث فاث 'حثريهرل فشسنس' سثذفهخر." +"فاث ثطثذعفهدث سعووشقغ قثحخقف هس زثهرل ذقثشفثي. فخ دهثص فاث سفشفعس خب فاث " +"قثحخقف, سثث حثريهرل هرسفقعذفخق فشسنس زثمخص." #: lms/djangoapps/instructor/views/api.py msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." msgstr "" -"شر ثطثذعفهدث سعووشقغ قثحخقف هس ذعققثرفمغ هر حقخلقثسس. فخ دهثص فاث سفشفعس خب " -"فاث قثحخقف, سثث فاث 'حثريهرل فشسنس' سثذفهخر. صاثر ذخوحمثفثي, فاث قثحخقف صهمم" -" زث شدشهمشزمث بخق يخصرمخشي هر فاث فشزمث زثمخص. غخع صهمم زث شزمث فخ يخصرمخشي " -"فاث قثحخقف صاثر هف هس ذخوحمثفث." +"فاث ثطثذعفهدث سعووشقغ قثحخقف هس ذعققثرفمغ زثهرل ذقثشفثي. فخ دهثص فاث سفشفعس " +"خب فاث قثحخقف, سثث حثريهرل هرسفقعذفخق فشسنس زثمخص. غخع صهمم زث شزمث فخ " +"يخصرمخشي فاث قثحخقف صاثر هف هس ذخوحمثفث." #: lms/djangoapps/instructor/views/api.py msgid "Could not parse amount as a decimal" @@ -6043,39 +6113,39 @@ msgstr "ذشررخف قثسذخقث صهفا شمم_سفعيثرفس شري عر #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" -"غخعق لقشيث قثحخقف هس زثهرل لثرثقشفثي! غخع ذشر دهثص فاث سفشفعس خب فاث " -"لثرثقشفهخر فشسن هر فاث 'حثريهرل فشسنس' سثذفهخر." +"فاث لقشيث قثحخقف هس زثهرل ذقثشفثي. فخ دهثص فاث سفشفعس خب فاث قثحخقف, سثث " +"حثريهرل هرسفقعذفخق فشسنس زثمخص." #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" -"ش لقشيث قثحخقف لثرثقشفهخر فشسن هس شمقثشيغ هر حقخلقثسس. ذاثذن فاث 'حثريهرل " -"فشسنس' فشزمث بخق فاث سفشفعس خب فاث فشسن. صاثر ذخوحمثفثي, فاث قثحخقف صهمم زث " -"شدشهمشزمث بخق يخصرمخشي هر فاث فشزمث زثمخص." +"فاث لقشيث قثحخقف هس ذعققثرفمغ زثهرل ذقثشفثي. فخ دهثص فاث سفشفعس خب فاث " +"قثحخقف, سثث حثريهرل هرسفقعذفخق فشسنس زثمخص. غخع صهمم زث شزمث فخ يخصرمخشي فاث" +" قثحخقف صاثر هف هس ذخوحمثفث." #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" -"غخعق حقخزمثو لقشيث قثحخقف هس زثهرل لثرثقشفثي! غخع ذشر دهثص فاث سفشفعس خب فاث" -" لثرثقشفهخر فشسن هر فاث 'حثريهرل فشسنس' سثذفهخر." +"فاث حقخزمثو لقشيث قثحخقف هس زثهرل ذقثشفثي. فخ دهثص فاث سفشفعس خب فاث قثحخقف," +" سثث حثريهرل هرسفقعذفخق فشسنس زثمخص." #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" -"ش حقخزمثو لقشيث قثحخقف هس شمقثشيغ زثهرل لثرثقشفثي. ذاثذن فاث 'حثريهرل فشسنس'" -" فشزمث بخق فاث سفشفعس خب فاث فشسن. صاثر ذخوحمثفثي, فاث قثحخقف صهمم زث " -"شدشهمشزمث بخق يخصرمخشي هر فاث فشزمث زثمخص." +"ش حقخزمثو لقشيث قثحخقف هس شمقثشيغ زثهرل لثرثقشفثي. فخ دهثص فاث سفشفعس خب فاث" +" قثحخقف, سثث حثريهرل هرسفقعذفخق فشسنس زثمخص. غخع صهمم زث شزمث فخ يخصرمخشي " +"فاث قثحخقف صاثر هف هس ذخوحمثفث." #: lms/djangoapps/instructor/views/api.py msgid "Successfully changed due date for student {0} for {1} to {2}" @@ -6214,13 +6284,12 @@ msgid "Data Download" msgstr "يشفش يخصرمخشي" #: lms/djangoapps/instructor/views/instructor_dashboard.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Analytics" -msgstr "شرشمغفهذس" +msgid "For analytics about your course, go to {analytics_dashboard_name}." +msgstr "بخق شرشمغفهذس شزخعف غخعق ذخعقسث, لخ فخ {analytics_dashboard_name}." #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." -msgstr "يثوخلقشحاهذ يشفش هس رخص شدشهمشزمث هر {dashboard_link}." +msgid "Analytics" +msgstr "شرشمغفهذس" #: lms/djangoapps/instructor/views/instructor_dashboard.py #: lms/templates/courseware/legacy_instructor_dashboard.html @@ -6496,7 +6565,6 @@ msgid "Title" msgstr "فهفمث" #: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "غثشق خب زهقفا" @@ -7169,10 +7237,6 @@ msgstr "ذخووثرفس" msgid "University" msgstr "عرهدثقسهفغ" -#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html -msgid "Course" -msgstr "ذخعقسث" - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "ذخعقسث شررخعرذث يشفث" @@ -8073,6 +8137,10 @@ msgstr "فاث سعححمهثي ذخعقسث هي {course_id} هس رخف دشم msgid "course_id must be provided" msgstr "ذخعقسث_هي وعسف زث حقخدهيثي" +#: lms/djangoapps/teams/views.py +msgid "The supplied topic id {topic_id} is not valid" +msgstr "فاث سعححمهثي فخحهذ هي {topic_id} هس رخف دشمهي" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "فثطف_سثشقذا هس رخف غثف سعححخقفثي." @@ -8081,14 +8149,14 @@ msgstr "فثطف_سثشقذا هس رخف غثف سعححخقفثي." msgid "last_activity is not yet supported" msgstr "مشسف_شذفهدهفغ هس رخف غثف سعححخقفثي" -#: lms/djangoapps/teams/views.py -msgid "The supplied course_id {course_id} is not valid." -msgstr "فاث سعححمهثي ذخعقسث_هي {course_id} هس رخف دشمهي." - #: lms/djangoapps/teams/views.py msgid "The ordering {} is not supported" msgstr "فاث خقيثقهرل {} هس رخف سعححخقفثي" +#: lms/djangoapps/teams/views.py +msgid "The supplied course_id {course_id} is not valid." +msgstr "فاث سعححمهثي ذخعقسث_هي {course_id} هس رخف دشمهي." + #: lms/djangoapps/teams/views.py msgid "username or team_id must be specified." msgstr "عسثقرشوث خق فثشو_هي وعسف زث سحثذهبهثي." @@ -8141,6 +8209,18 @@ msgstr "غخعق بشذث صشس رخف دهسهزمث هر غخعق سثمب-ح msgid "There was an error verifying your ID photos." msgstr "فاثقث صشس شر ثققخق دثقهبغهرل غخعق هي حاخفخس." +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "فاث ذخعقسث بخق صاهذا فاهس يثشيمهرث شححمهثس" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" +"فاث يشفثفهوث شبفثق صاهذا عسثقس شقث رخ مخرلثق شممخصثي فخ سعزوهف حاخفخس بخق " +"دثقهبهذشفهخر." + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "هرفقخ" @@ -8991,6 +9071,10 @@ msgstr "" msgid "A cohort with the same name already exists." msgstr "ش ذخاخقف صهفا فاث سشوث رشوث شمقثشيغ ثطهسفس." +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "ذخعقسث ذقثيهف ثمهلهزهمهفغ" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -9053,6 +9137,26 @@ msgstr "" "*شبفثق* حشغهرل بخق فاث ذقثيهف فخ لثف ذقثيهف بخق ش ذقثيهف ذخعقسث شلشهرسف ش " "ذقثيهف حقخدهيثق." +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" +"حمشهر فثطف خق افوم ذخرفثرف بخق يهسحمشغهرل ذعسفخو وثسسشلث هرسهيث ذقثيهف " +"ثمهلهزهمهفغ ثوشهم ذخرفثرف صاهذا هس سثرف صاثر عسثق اشس وثف شمم ذقثيهف " +"ثمهلهزهمهفغ قثضعهقثوثرفس." + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" +"حمشهر فثطف خق افوم ذخرفثرف بخق يهسحمشغهرل ذعسفخو وثسسشلث هرسهيث ذقثيهف " +"قثذثهحف ثوشهم ذخرفثرف صاهذا هس سثرف *شبفثق* حشغهرل فخ لثف ذقثيهف بخق ش " +"ذقثيهف ذخعقسث." + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "يثشيمهرث بخق حعقذاشسهرل شري قثضعثسفهرل ذقثيهف." @@ -9690,9 +9794,7 @@ msgstr "حشلث رخف بخعري" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -9828,6 +9930,11 @@ msgstr "دهسهف غخعق {link_start}يشسازخشقي{link_end} فخ سثث msgid "Course Navigation" msgstr "ذخعقسث رشدهلشفهخر" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "شذذخعرف" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py msgid "Help" @@ -10011,7 +10118,8 @@ msgstr "مثشقر وخقث" msgid "Starts" msgstr "سفشقفس" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "يشسازخشقي" @@ -10040,12 +10148,12 @@ msgid "Clear search" msgstr "ذمثشق سثشقذا" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" -msgstr "صشرف فخ ذاشرلث غخعق شذذخعرف سثففهرلس?" +msgid "Find New Courses" +msgstr "بهري رثص ذخعقسثس" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." -msgstr "ذمهذن فاث شققخص رثطف فخ غخعق عسثقرشوث شزخدث." +msgid "Account Status Info" +msgstr "شذذخعرف سفشفعس هربخ" #: lms/templates/dashboard.html msgid "Order History" @@ -10659,27 +10767,23 @@ msgid "More options dropdown" msgstr "وخقث خحفهخرس يقخحيخصر" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "شذذخعرف سثففهرلس" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" -msgstr "وغ حقخبهمث" +msgid "Profile" +msgstr "حقخبهمث" #: lms/templates/navigation-edx.html lms/templates/navigation.html #: lms/templates/shoppingcart/shopping_cart.html msgid "Shopping Cart" msgstr "ساخححهرل ذشقف" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" -msgstr "قثلهسفثق" - #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "Sign in" msgstr "سهلر هر" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +#: lms/templates/register.html +msgid "Register" +msgstr "قثلهسفثق" + #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "" "Warning: Your browser is not fully supported. We strongly " @@ -10701,10 +10805,6 @@ msgstr "سغسشيوهر" msgid "Schools" msgstr "سذاخخمس" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "قثلهسفثق رخص" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -11765,6 +11865,12 @@ msgstr "حقهرف خق ساشقث غخعق ذثقفهبهذشفث:" msgid "I completed the {course_title} course on {platform_name}." msgstr "ه ذخوحمثفثي فاث {course_title} ذخعقسث خر {platform_name}." +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" +"ه ذخوحمثفثي ش ذخعقسث خر {platform_name}. فشنث ش مخخن شف وغ ذثقفهبهذشفث." + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "ذمهذن فاث مهرن فخ سثث وغ ذثقفهبهذشفث." @@ -11773,6 +11879,15 @@ msgstr "ذمهذن فاث مهرن فخ سثث وغ ذثقفهبهذشفث." msgid "Post on Facebook" msgstr "حخسف خر بشذثزخخن" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "ساشقث خر فصهففثق" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "فصثثف فاهس شذذخوحمهساوثرف. حخح عح صهريخص." + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "شيي فخ مهرنثيهر حقخبهمث" @@ -12030,6 +12145,10 @@ msgstr "{chapter}, ذعققثرف ذاشحفثق" msgid "due {date}" msgstr "يعث {date}" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "فاهس سثذفهخر هس لقشيثي." + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -12133,10 +12252,6 @@ msgstr "ذمشسسثس ثري" msgid "Estimated Effort" msgstr "ثسفهوشفثي ثببخقف" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "حقهذث" - #: lms/templates/courseware/course_about.html msgid "Prerequisites" msgstr "حقثقثضعهسهفثس" @@ -12167,14 +12282,26 @@ msgstr "ذخعقسث دهثص" msgid "View this course as:" msgstr "دهثص فاهس ذخعقسث شس:" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "سحثذهبهذ سفعيثرف" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "سفعيثرف هر {content_group}" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" +msgid "Username or email:" +msgstr "عسثقرشوث خق ثوشهم:" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" msgstr "سثف حقثدهثص وخيث" +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." +msgstr "غخع شقث رخص دهثصهرل فاث ذخعقسث شس {user_name}." + #: lms/templates/courseware/course_navigation.html msgid "Course Material" msgstr "ذخعقسث وشفثقهشم" @@ -12209,6 +12336,10 @@ msgstr "ثطحمخقث ذخعقسثس بقخو {platform_name}." msgid "{platform_name} Logo" msgstr "{platform_name} مخلخ" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "مهسف خب ذخعقسثس" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "قثبهرث غخعق سثشقذا" @@ -12514,78 +12645,6 @@ msgstr "" msgid "To send email, visit the Email section of the Instructor Dashboard." msgstr "فخ سثري ثوشهم, دهسهف فاث ثوشهم سثذفهخر خب فاث هرسفقعذفخق يشسازخشقي." -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "رخ شرشمغفهذس شقث شدشهمشزمث شف فاهس فهوث." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "سفعيثرف شذفهدهفغ يشغ زغ يشغ" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "يشغ" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "سفعيثرفس" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "سذخقث يهسفقهزعفهخر بخق حقخزمثوس" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "وشط" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "حخهرفس ثشقرثي (رعو سفعيثرفس)" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "فاثقث هس رخ يشفش شدشهمشزمث فخ يهسحمشغ شف فاهس فهوث." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "" -"مخشيهرل فاث مشفثسف لقشحاس بخق غخع; يثحثريهرل خر غخعق ذمشسس سهظث, فاهس وشغ " -"فشنث ش بثص وهرعفثس." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "ذخعرف خب سفعيثرفس فاشف خحثرثي ش سعزسثذفهخر" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr "لقشيث يهسفقهزعفهخر حثق حقخزمثو" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "فاثقث شقث رخ حقخزمثوس هر فاهس سثذفهخر." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "سفعيثرفس شرسصثقهرل ذخققثذفمغ" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "رعوزثق خب سفعيثرفس" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" -"سفعيثرف يهسفقهزعفهخر حثق ذخعرفقغ, شمم ذخعقسثس, سثح 12 فخ خذف 17, 1 سثقدثق " -"(ساخصر اثقث شس شر ثطشوحمث):" - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "حثريهرل هرسفقعذفخق فشسنس" @@ -12757,12 +12816,14 @@ msgid "Requirements for Course Credit" msgstr "قثضعهقثوثرفس بخق ذخعقسث ذقثيهف" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." -msgstr "غخع شقث رخ مخرلثق ثمهلهزمث بخق فاهس ذخعقسث." +msgid "{student_name}, you are no longer eligible for credit in this course." +msgstr "{student_name}, غخع شقث رخ مخرلثق ثمهلهزمث بخق ذقثيهف هر فاهس ذخعقسث." #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." -msgstr "غخع اشدث وثف فاث قثضعهقثوثرفس بخق ذقثيهف هر فاهس ذخعقسث." +msgid "" +"{student_name}, you have met the requirements for credit in this course." +msgstr "" +"{student_name}, غخع اشدث وثف فاث قثضعهقثوثرفس بخق ذقثيهف هر فاهس ذخعقسث." #: lms/templates/courseware/progress.html msgid "{link} to purchase course credit." @@ -12828,6 +12889,56 @@ msgstr "" "غخع صثقث وخسف قثذثرفمغ هر {section_link}. هب غخع'قث يخرث صهفا فاشف, ذاخخسث " "شرخفاثق سثذفهخر خر فاث مثبف." +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "اه {name}," + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" +"ذخرلقشفعمشفهخرس! غخع شقث ثمهلهزمث فخ قثذثهدث عرهدثقسهفغ ذقثيهف بقخو ثيط " +"حشقفرثقس! ذمهذن {link} فخ لثف غخعق ذقثيهف رخص." + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" +"ذقثيهف بقخو ذشر اثمح غخع لثف ش تعوح سفشقف خر غخعق عرهدثقسهفغ يثلقثث, بهرهسا " +"ش يثلقثث شمقثشيغ سفشقفثي, خق بعمبهمم قثضعهقثوثرفس شف ش يهببثقثرف شذشيثوهذ " +"هرسفهفعفهخر." + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" +"فخ لثف عرهدثقسهفغ ذقثيهف بخق {course_name}, سهوحمغ لخ فخ غخعق {link} شري " +"ذمهذن فاث غثممخص \"لثف ذقثيهف\" زعففخر. رخ شححمهذشفهخر, فقشرسذقهحف, خق لقشيث" +" قثحخقف هس قثضعهقثي." + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" +"صث اخحث غخع ثرتخغثي فاث ذخعقسث, شري صث اخحث فخ سثث غخع هر بعفعقث ثيط " +"ذخعقسثس!" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "فاث ثيط فثشو" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "بهري وخقث ثيط ذخعقسثس غخع ذشر فشنث بخق عرهدثقسهفغ ذقثيهف." + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -12961,10 +13072,6 @@ msgstr "ساشقث خر بشذثزخخن" msgid "I'm learning on {platform_name}:" msgstr "ه'و مثشقرهرل خر {platform_name}:" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "ساشقث خر فصهففثق" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "ذخعقسث خحفهخرس يقخحيخصر" @@ -13927,11 +14034,6 @@ msgstr "فاهس ثوشهم صشس شعفخوشفهذشممغ سثرف بقخو msgid "You have been invited to a beta test for {course_name}" msgstr "غخع اشدث زثثر هردهفثي فخ ش زثفش فثسف بخق {course_name}" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "اه {name}," - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "فاشرن غخع بخق غخعق حعقذاشسث خب " @@ -15506,34 +15608,6 @@ msgstr "ذعسفخوثق'س حعقذاشسث خقيثق خق خفاثق قثبث msgid "Send me a copy of the invoice" msgstr "سثري وث ش ذخحغ خب فاث هردخهذث" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "سذخقث يهسفقهزعفهخر" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "" -"فاث ذاشقف زثمخص يهسحمشغس فاث سذخقث يهسفقهزعفهخر بخق ثشذا سفشريشقي حقخزمثو هر" -" غخعق ذمشسس, سحثذهبهثي زغ فاث حقخزمثو'س عقم رشوث." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "" -"سذخقثس شقث ساخصر صهفاخعف صثهلافهرل شححمهثي, سخ هب غخعق حقخزمثو ذخرفشهرس 2 " -"ضعثسفهخرس, هف صهمم يهسحمشغ شس اشدهرل ش فخفشم خب 2 حخهرفس." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "مخشيهرل حقخزمثو مهسف..." - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "لثريثق يهسفقهزعفهخر" - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "هرسفقعذفخق يشسازخشقي" @@ -15796,6 +15870,10 @@ msgstr "" msgid "Add CCX Coach" msgstr "شيي ذذط ذخشذا" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "فاثقث هس رخ يشفش شدشهمشزمث فخ يهسحمشغ شف فاهس فهوث." + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "عسث قثمخشي لقشحاس فخ قثبقثسا فاث لقشحاس." @@ -15848,6 +15926,10 @@ msgstr "" msgid "Download Problem Data for all Problems as a CSV" msgstr "يخصرمخشي حقخزمثو يشفش بخق شمم حقخزمثوس شس ش ذسد" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr "لقشيث يهسفقهزعفهخر حثق حقخزمثو" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "يخصرمخشي سفعيثرف خحثرثي شس ش ذسد" @@ -15860,6 +15942,10 @@ msgstr "يخصرمخشي سفعيثرف لقشيثس شس ش ذسد" msgid "This is a partial list, to view all students download as a csv." msgstr "فاهس هس ش حشقفهشم مهسف, فخ دهثص شمم سفعيثرفس يخصرمخشي شس ش ذسد." +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "فاثقث شقث رخ حقخزمثوس هر فاهس سثذفهخر." + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "سثري ثوشهم" @@ -16698,6 +16784,10 @@ msgstr "حقهذث حثق سفعيثرف:" msgid "Discount Applied:" msgstr "يهسذخعرف شححمهثي:" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "سفعيثرفس" + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -16962,6 +17052,10 @@ msgstr "" msgid "Currently the {platform_name} servers are overloaded" msgstr "ذعققثرفمغ فاث {platform_name} سثقدثقس شقث خدثقمخشيثي" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "شذذخعرف سثففهرلس" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "حمثشسث صشهف" @@ -17074,18 +17168,30 @@ msgstr "فاث بخممخصهرل ثققخق خذذعققثي صاهمث ثيه msgid "Re-Verify for {course_name}" msgstr "قث-دثقهبغ بخق {course_name}" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "دثقهبهذشفهخر يثشيمهرث اشس حشسسثي" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "عحلقشيث يثشيمهرث اشس حشسسثي" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." msgstr "" -"فاث دثقهبهذشفهخر يثشيمهرث بخق {course_name} صشس {date}. دثقهبهذشفهخر هس رخ " +"فاث دثقهبهذشفهخر يثشيمهرث بخق {course_name} صشس {date}. دثقهبهذشفهخر هس رخ " "مخرلثق شدشهمشزمث." +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" +"فاث يثشيمهرث فخ عحلقشيث فخ ش دثقهبهثي ذثقفهبهذشفث بخق فاهس ذخعقسث اشس " +"حشسسثي. غخع ذشر سفهمم ثشقر شر اخرخق ذخيث ذثقفهبهذشفث." + #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." msgstr "عحلقشيث غخعق ثرقخمموثرف بخق {course_name}." @@ -20517,10 +20623,6 @@ msgstr "ثطحخقف" msgid "Current Library:" msgstr "ذعققثرف مهزقشقغ:" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "شذذخعرف" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "شذذخعرف رشدهلشفهخر" diff --git a/conf/locale/rtl/LC_MESSAGES/djangojs.mo b/conf/locale/rtl/LC_MESSAGES/djangojs.mo index 26017fb883..e460ecdc48 100644 Binary files a/conf/locale/rtl/LC_MESSAGES/djangojs.mo and b/conf/locale/rtl/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/rtl/LC_MESSAGES/djangojs.po b/conf/locale/rtl/LC_MESSAGES/djangojs.po index bf3169a4bf..a80c4c3956 100644 --- a/conf/locale/rtl/LC_MESSAGES/djangojs.po +++ b/conf/locale/rtl/LC_MESSAGES/djangojs.po @@ -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-07-13 04:40+0000\n" -"PO-Revision-Date: 2015-07-13 04:42:08.623413\n" +"POT-Creation-Date: 2015-07-22 18:11+0000\n" +"PO-Revision-Date: 2015-07-22 18:12:54.993319\n" "Last-Translator: \n" "Language-Team: openedx-translation \n" "MIME-Version: 1.0\n" @@ -2295,22 +2295,41 @@ msgstr "قثحمغ" msgid "Tags:" 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" msgstr "رشوث" +#: lms/djangoapps/teams/static/teams/js/collections/team.js +msgid "open_slots" +msgstr "خحثر_سمخفس" + #: lms/djangoapps/teams/static/teams/js/collections/topic.js msgid "team count" msgstr "فثشو ذخعرف" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "%(member_count)s / %(max_member_count)s وثوزثق" +msgstr[1] "%(member_count)s / %(max_member_count)s وثوزثقس" + +#: 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/teams.js +msgid "Create new team" +msgstr "ذقثشفث رثص فثشو" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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" @@ -2324,6 +2343,14 @@ msgstr "وغ فثشوس" msgid "Browse" msgstr "زقخصسث" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "فاث حشلث \"%(route)s\" ذخعمي رخف زث بخعري." + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "فاث فخحهذ \"%(topic)s\" ذخعمي رخف زث بخعري." + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2376,22 +2403,6 @@ msgstr "ثققخق لثرثقشفهرل لقشيثس. حمثشسث فقغ شلش msgid "Error generating problem grade report. Please try again." msgstr "ثققخق لثرثقشفهرل حقخزمثو لقشيث قثحخقف. حمثشسث فقغ شلشهر." -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "عرشدشهمشزمث وثفقهذ يهسحمشغ." - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "ثققخق بثفذاهرل لقشيث يهسفقهزعفهخرس." - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "مشسف عحيشفثي: <%= timestamp %>" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "<%= num_students %> سفعيثرفس سذخقثي." - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3208,6 +3219,12 @@ msgstr "غخعق يخرشفهخر ذخعمي رخف زث سعزوهففثي." msgid "An error occurred. Please try again later." msgstr "شر ثققخق خذذعققثي. حمثشسث فقغ شلشهر مشفثق." +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "دهثصهرل %س ذخعقسث" +msgstr[1] "دهثصهرل %س ذخعقسثس" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "صث ذخعمير'ف بهري شرغ قثسعمفس بخق \"%س\"." @@ -3221,8 +3238,8 @@ msgstr "فاثقث صشس شر ثققخق, فقغ سثشقذاهرل شلشهر. msgid "Focus grabber" msgstr "بخذعس لقشززثق" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." @@ -3230,6 +3247,22 @@ msgstr "" "شر ثققخق اشس خذذعققثي. وشنث سعقث فاشف غخع شقث ذخررثذفثي فخ فاث هرفثقرثف, شري" " فاثر فقغ قثبقثساهرل فاث حشلث." +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "اهيث رخفثس" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "رخفثس دهسهزمث" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "ساخص رخفثس" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "رخفثس اهييثر" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3240,22 +3273,6 @@ msgstr "" msgid "Current tab" msgstr "ذعققثرف فشز" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "اهيث رخفثس" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "رخفثس دهسهزمث" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "ساخص رخفثس" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "رخفثس اهييثر" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "مخذشفهخر هر ذخعقسث" @@ -5083,6 +5100,23 @@ msgstr "قثوخدث شمم" msgid "remove" msgstr "قثوخدث" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "لثففثطف(" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "%s" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" +"" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "فاشرن غخع! صث اشدث قثذثهدثي غخعق حشغوثرف." @@ -5180,10 +5214,6 @@ msgstr "مثسس..." msgid "LEARN MORE" msgstr "مثشقر وخقث" -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "لثففثطف(" - #: lms/templates/discovery/result_item.underscore msgid "Starts" msgstr "سفشقفس" @@ -6148,10 +6178,6 @@ msgstr "سفشفعس" msgid "Common Problem Types" msgstr "ذخووخر حقخزمثو فغحثس" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "ذخووخر حقخزمثوس صهفا اهرفس شري بثثيزشذن" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "شيي رثص ذخوحخرثرف" diff --git a/conf/locale/ru/LC_MESSAGES/django.mo b/conf/locale/ru/LC_MESSAGES/django.mo index 34f347176c..9296399b17 100644 Binary files a/conf/locale/ru/LC_MESSAGES/django.mo and b/conf/locale/ru/LC_MESSAGES/django.mo differ diff --git a/conf/locale/ru/LC_MESSAGES/django.po b/conf/locale/ru/LC_MESSAGES/django.po index d2677734c5..ad5a0c8683 100644 --- a/conf/locale/ru/LC_MESSAGES/django.po +++ b/conf/locale/ru/LC_MESSAGES/django.po @@ -23,6 +23,7 @@ # mcha121 , 2014 # mchalyk , 2014 # Michael Savin , 2015 +# Natalia Vavilina , 2015 # Ничик Дмитрий Валерьевич , 2013 # Nikita V. Ignatchenko , 2014 # Nikolay K Medvedev , 2014 @@ -40,6 +41,7 @@ # Weyedide , 2014 # Yana Malinovskaya , 2014 # Yermek Alimzhanov , 2015 +# YummyTranslations EDX , 2015 # tonybond , 2014 # Андрей Сандлер , 2013 # #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-# @@ -116,6 +118,7 @@ # Weyedide , 2014 # Yana Malinovskaya , 2014 # Yermek Alimzhanov , 2015 +# YummyTranslations EDX , 2015 # Pavel Zamyshliaev, 2014 # tonybond , 2014 # Андрей Сандлер , 2013 @@ -177,10 +180,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:33+0000\n" -"PO-Revision-Date: 2015-07-07 20:57+0000\n" +"POT-Creation-Date: 2015-07-22 17:45+0000\n" +"PO-Revision-Date: 2015-07-13 21:12+0000\n" "Last-Translator: Weyedide \n" -"Language-Team: Russian (http://www.transifex.com/p/edx-platform/language/ru/)\n" +"Language-Team: Russian (http://www.transifex.com/projects/p/edx-platform/language/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -198,8 +201,6 @@ msgstr "Обсуждение" #: cms/djangoapps/contentstore/views/component.py #: lms/djangoapps/class_dashboard/dashboard_data.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Problem" msgstr "Задача" @@ -296,6 +297,69 @@ msgstr "" "Перечислите домены, которым разрешены междоменные запросы к этому сайту. " "Пожалуйста, укажите каждый домен в отдельной строке." +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py +msgid "Course" +msgstr "Курс" + +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/annotatable_module.py +#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/combined_open_ended_module.py +#: common/lib/xmodule/xmodule/discussion_module.py +#: common/lib/xmodule/xmodule/html_module.py +#: common/lib/xmodule/xmodule/imageannotation_module.py +#: common/lib/xmodule/xmodule/library_content_module.py +#: common/lib/xmodule/xmodule/lti_module.py +#: common/lib/xmodule/xmodule/peer_grading_module.py +#: common/lib/xmodule/xmodule/split_test_module.py +#: common/lib/xmodule/xmodule/textannotation_module.py +#: common/lib/xmodule/xmodule/videoannotation_module.py +#: common/lib/xmodule/xmodule/word_cloud_module.py +#: cms/templates/container.html cms/templates/library.html +msgid "Display Name" +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "" @@ -604,7 +668,7 @@ msgstr "" #: common/djangoapps/student/models.py msgid "The ISO 639-1 language code for this language." -msgstr "" +msgstr "Код этого языка по стандарту ISO 639-1." #: common/djangoapps/student/models.py msgid "Namespace of enrollment attribute" @@ -659,8 +723,8 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" #: common/djangoapps/student/views.py @@ -1631,23 +1695,6 @@ msgstr "" msgid "XML data for the annotation" msgstr "" -#: common/lib/xmodule/xmodule/annotatable_module.py -#: common/lib/xmodule/xmodule/capa_base.py -#: common/lib/xmodule/xmodule/combined_open_ended_module.py -#: common/lib/xmodule/xmodule/discussion_module.py -#: common/lib/xmodule/xmodule/html_module.py -#: common/lib/xmodule/xmodule/imageannotation_module.py -#: common/lib/xmodule/xmodule/library_content_module.py -#: common/lib/xmodule/xmodule/lti_module.py -#: common/lib/xmodule/xmodule/peer_grading_module.py -#: common/lib/xmodule/xmodule/split_test_module.py -#: common/lib/xmodule/xmodule/textannotation_module.py -#: common/lib/xmodule/xmodule/videoannotation_module.py -#: common/lib/xmodule/xmodule/word_cloud_module.py -#: cms/templates/container.html cms/templates/library.html -msgid "Display Name" -msgstr "" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1766,9 +1813,8 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" #: common/lib/xmodule/xmodule/capa_base.py @@ -3148,10 +3194,6 @@ msgstr "" msgid "Library Version" msgstr "" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "" @@ -3720,10 +3762,11 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py @@ -4716,7 +4759,7 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" @@ -4832,6 +4875,34 @@ msgstr "" msgid "Visit a course wiki to add an article." msgstr "" +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" + #: lms/djangoapps/courseware/tabs.py #: lms/templates/courseware/courseware-error.html msgid "Courseware" @@ -4928,7 +4999,7 @@ msgstr "" #: lms/djangoapps/courseware/views.py msgid "Certificate is being created." -msgstr "" +msgstr "Создание сертификата" #: lms/djangoapps/courseware/features/video.py msgid "ERROR: No playable video sources found!" @@ -5458,9 +5529,10 @@ msgstr "" msgid "Gender" msgstr "Пол" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html +#: lms/djangoapps/instructor/views/api.py +#: lms/djangoapps/instructor_task/tasks_helper.py msgid "Level of Education" -msgstr "Уровень образования" +msgstr "" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/register.html @@ -5478,28 +5550,22 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5557,29 +5623,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5633,28 +5698,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5786,12 +5851,12 @@ msgid "Data Download" msgstr "Скачивание данных" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Analytics" -msgstr "Аналитика" +msgid "For analytics about your course, go to {analytics_dashboard_name}." +msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." -msgstr "" +msgid "Analytics" +msgstr "Аналитика" #: lms/djangoapps/instructor/views/instructor_dashboard.py #: lms/templates/courseware/legacy_instructor_dashboard.html @@ -6065,7 +6130,6 @@ msgid "Title" msgstr "Заголовок" #: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "" @@ -6285,7 +6349,7 @@ msgstr "" #: lms/djangoapps/lms_xblock/mixin.py msgid "Default Tab" -msgstr "" +msgstr "Вкладка по умолчанию" #: lms/djangoapps/lms_xblock/mixin.py msgid "" @@ -6672,10 +6736,6 @@ msgstr "" msgid "University" msgstr "" -#: lms/djangoapps/shoppingcart/reports.py -msgid "Course" -msgstr "Курс" - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "" @@ -7377,6 +7437,10 @@ msgstr "" msgid "course_id must be provided" msgstr "" +#: lms/djangoapps/teams/views.py +msgid "The supplied topic id {topic_id} is not valid" +msgstr "" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "" @@ -7386,11 +7450,11 @@ msgid "last_activity is not yet supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The supplied course_id {course_id} is not valid." +msgid "The ordering {} is not supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The ordering {} is not supported" +msgid "The supplied course_id {course_id} is not valid." msgstr "" #: lms/djangoapps/teams/views.py @@ -7443,6 +7507,16 @@ msgstr "" msgid "There was an error verifying your ID photos." msgstr "" +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "" @@ -8235,6 +8309,10 @@ msgstr "" msgid "A cohort with the same name already exists." msgstr "" +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -8282,13 +8360,27 @@ msgid "" "credit provider." msgstr "" +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "" #: openedx/core/djangoapps/profile_images/images.py msgid "bytes" -msgstr "" +msgstr "байт" #: openedx/core/djangoapps/profile_images/images.py msgid "KB" @@ -8409,7 +8501,7 @@ msgstr "" #: openedx/core/djangoapps/user_api/accounts/api.py msgid "The '{field_name}' field cannot be edited." -msgstr "" +msgstr "Поле '{field_name}' не может быть отредактировано." #: openedx/core/djangoapps/user_api/preferences/api.py msgid "Delete failed for user preference '{preference_key}'." @@ -8865,9 +8957,7 @@ msgstr "Страница не найдена" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -9005,6 +9095,11 @@ msgstr "" msgid "Course Navigation" msgstr "" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html msgid "Help" @@ -9037,7 +9132,7 @@ msgstr "" #: common/templates/license.html msgid "Creative Commons licensed content, with terms as follow:" -msgstr "" +msgstr "Содержимое защищено лицензией Creative Commons на следующих условиях:" #: common/templates/license.html msgid "Some Rights Reserved" @@ -9165,7 +9260,8 @@ msgstr "" msgid "Starts" msgstr "" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "" @@ -9194,11 +9290,11 @@ msgid "Clear search" msgstr "" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" +msgid "Find New Courses" msgstr "" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." +msgid "Account Status Info" msgstr "" #: lms/templates/dashboard.html @@ -9785,12 +9881,7 @@ msgid "More options dropdown" msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" +msgid "Profile" msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html @@ -9798,14 +9889,15 @@ msgstr "" msgid "Shopping Cart" msgstr "Корзина" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" -msgstr "Регистрация" - #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "Sign in" msgstr "" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +#: lms/templates/register.html +msgid "Register" +msgstr "Регистрация" + #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "" "Warning: Your browser is not fully supported. We strongly " @@ -9825,10 +9917,6 @@ msgstr "" msgid "Schools" msgstr "Университеты" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -10831,6 +10919,11 @@ msgstr "" msgid "I completed the {course_title} course on {platform_name}." msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "" @@ -10839,6 +10932,15 @@ msgstr "" msgid "Post on Facebook" msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "" @@ -11085,6 +11187,10 @@ msgstr "{chapter}, текущая глава" msgid "due {date}" msgstr "" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "" + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -11184,10 +11290,6 @@ msgstr "" msgid "Estimated Effort" msgstr "" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Prerequisites" msgstr "" @@ -11216,12 +11318,24 @@ msgstr "" msgid "View this course as:" msgstr "" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" +msgid "Username or email:" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." msgstr "" #: lms/templates/courseware/course_navigation.html @@ -11256,6 +11370,10 @@ msgstr "" msgid "{platform_name} Logo" msgstr "" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "" @@ -11519,74 +11637,6 @@ msgstr "" msgid "To send email, visit the Email section of the Instructor Dashboard." msgstr "" -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "Активность студентов по дням" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "День" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "Студенты" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "Максимум" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "В настоящий момент данных для вывода нет." - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "Студенты, отвечающие верно" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "Количество студентов" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "" @@ -11753,11 +11803,12 @@ msgid "Requirements for Course Credit" msgstr "" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." +msgid "{student_name}, you are no longer eligible for credit in this course." msgstr "" #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." +msgid "" +"{student_name}, you have met the requirements for credit in this course." msgstr "" #: lms/templates/courseware/progress.html @@ -11824,6 +11875,46 @@ msgstr "" "В последний раз Вы были в разделе {section_link}. Если Вы закончили, " "выберите другой раздел слева." +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "" + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -11939,10 +12030,6 @@ msgstr "" msgid "I'm learning on {platform_name}:" msgstr "" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "" @@ -12839,11 +12926,6 @@ msgstr "" msgid "You have been invited to a beta test for {course_name}" msgstr "" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "" - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "" @@ -13325,7 +13407,7 @@ msgstr "" #: lms/templates/emails/reverification_processed.txt msgid "Thanks," -msgstr "" +msgstr "Спасибо," #: lms/templates/emails/unenroll_email_allowedmessage.txt msgid "Dear Student," @@ -14247,30 +14329,6 @@ msgstr "" msgid "Send me a copy of the invoice" msgstr "" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "Распределение баллов" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "" - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "" @@ -14491,6 +14549,10 @@ msgstr "" msgid "Add CCX Coach" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "В настоящий момент данных для вывода нет." + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "" @@ -14539,6 +14601,10 @@ msgstr "" msgid "Download Problem Data for all Problems as a CSV" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "" @@ -14551,6 +14617,10 @@ msgstr "" msgid "This is a partial list, to view all students download as a csv." msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "" @@ -15313,6 +15383,10 @@ msgstr "" msgid "Discount Applied:" msgstr "" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "Студенты" + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -15550,6 +15624,10 @@ msgstr "" msgid "Currently the {platform_name} servers are overloaded" msgstr "" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "" @@ -15655,16 +15733,26 @@ msgstr "" msgid "Re-Verify for {course_name}" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." msgstr "" +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" + #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." msgstr "" @@ -16015,7 +16103,7 @@ msgstr "" #: cms/templates/checklists.html msgid "What are course checklists?" -msgstr "" +msgstr "Что такое контрольные списки курса?" #: cms/templates/checklists.html msgid "" @@ -16048,7 +16136,7 @@ msgstr "" #: cms/templates/component.html cms/templates/edit-tabs.html #: cms/templates/studio_xblock_wrapper.html msgid "Drag to reorder" -msgstr "" +msgstr "Перетащите для изменения порядка" #: cms/templates/container.html msgid "Open the courseware in the LMS" @@ -18596,10 +18684,6 @@ msgstr "" msgid "Current Library:" msgstr "" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "" @@ -19023,6 +19107,11 @@ msgid "" "\n" "The children of this article have had their parents deleted. You should probably find a new home for them." msgstr "" +"Статьи, которые потеряли своих родителей\n" +"===============================\n" +"\n" +"\n" +"У потомков этой статьи были удалены родители. Наверное, Вам следует найти им новый дом." #: wiki/models/urlpath.py msgid "Lost and found" diff --git a/conf/locale/ru/LC_MESSAGES/djangojs.mo b/conf/locale/ru/LC_MESSAGES/djangojs.mo index 64f044a521..911434a210 100644 Binary files a/conf/locale/ru/LC_MESSAGES/djangojs.mo and b/conf/locale/ru/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/ru/LC_MESSAGES/djangojs.po b/conf/locale/ru/LC_MESSAGES/djangojs.po index b79483d5c5..2cc0f1475d 100644 --- a/conf/locale/ru/LC_MESSAGES/djangojs.po +++ b/conf/locale/ru/LC_MESSAGES/djangojs.po @@ -36,6 +36,7 @@ # Weyedide , 2014-2015 # Weyedide , 2014 # Yana Malinovskaya , 2014 +# YummyTranslations EDX , 2015 # Pavel Zamyshliaev, 2014 # Андрей Сандлер , 2013 # Ничик Дмитрий Валерьевич , 2013 @@ -77,6 +78,7 @@ # webslavic , 2014 # Weyedide , 2014-2015 # Yana Malinovskaya , 2014 +# YummyTranslations EDX , 2015 # #-#-#-#-# underscore-studio.po (edx-platform) #-#-#-#-# # edX translation file # Copyright (C) 2015 edX @@ -99,10 +101,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:31+0000\n" -"PO-Revision-Date: 2015-07-10 19:12+0000\n" -"Last-Translator: Sarina Canelake \n" -"Language-Team: Russian (http://www.transifex.com/p/edx-platform/language/ru/)\n" +"POT-Creation-Date: 2015-07-22 17:43+0000\n" +"PO-Revision-Date: 2015-07-15 22:14+0000\n" +"Last-Translator: Weyedide \n" +"Language-Team: Russian (http://www.transifex.com/projects/p/edx-platform/language/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -135,6 +137,7 @@ msgstr "Сохранение" msgid "OK" 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/coffee/src/views/tabs.js @@ -147,6 +150,17 @@ msgstr "ОК" #: 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 +#: cms/templates/js/add-xblock-component-menu-problem.underscore +#: cms/templates/js/add-xblock-component-menu.underscore +#: cms/templates/js/certificate-editor.underscore +#: cms/templates/js/content-group-editor.underscore +#: cms/templates/js/course_info_handouts.underscore +#: cms/templates/js/course_info_update.underscore +#: cms/templates/js/edit-textbook.underscore +#: cms/templates/js/group-configuration-editor.underscore +#: cms/templates/js/section-name-edit.underscore +#: cms/templates/js/xblock-string-field-editor.underscore +#: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore msgid "Cancel" msgstr "Отмена" @@ -221,7 +235,7 @@ msgstr "Закрыть" #: common/lib/xmodule/xmodule/js/src/annotatable/display.js msgid "Show Annotations" -msgstr "" +msgstr "Показать пояснения" #: common/lib/xmodule/xmodule/js/src/annotatable/display.js msgid "Hide Annotations" @@ -241,7 +255,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/annotatable/display.js msgid "Reply to Annotation" -msgstr "" +msgstr "Ответить на пояснение" #. Translators: %(earned)s is the number of points earned. %(total)s is the #. total number of points (examples: 0/1, 1/1, 2/3, 5/10). The total number of @@ -1782,7 +1796,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/video/08_video_speed_control.js msgid "Speeds" -msgstr "" +msgstr "Скорость воспроизведения" #: common/lib/xmodule/xmodule/js/src/video/09_play_skip_control.js msgid "Skip" @@ -2216,7 +2230,7 @@ msgstr[3] "" #: common/static/js/vendor/ova/catch/js/catch.js msgid "User" -msgstr "" +msgstr "Пользователь" #: common/static/js/vendor/ova/catch/js/catch.js msgid "Annotation" @@ -2312,19 +2326,40 @@ msgstr "" msgid "Tags:" 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" msgstr "" +#: lms/djangoapps/teams/static/teams/js/collections/team.js +msgid "open_slots" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/collections/topic.js msgid "team count" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: 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/teams.js +msgid "Create new team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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 @@ -2339,6 +2374,14 @@ msgstr "" msgid "Browse" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "" + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2393,22 +2436,6 @@ msgstr "" msgid "Error generating problem grade report. Please try again." msgstr "" -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "Ошибка загрузки распределения оценок." - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "" - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3153,6 +3180,14 @@ msgstr "" msgid "An error occurred. Please try again later." msgstr "" +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "" @@ -3166,13 +3201,29 @@ msgstr "" msgid "Focus grabber" msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." msgstr "" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3182,22 +3233,6 @@ msgstr "" msgid "Current tab" msgstr "" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "" @@ -3491,10 +3526,9 @@ msgstr "" msgid "Reset your Password" msgstr "" -#: lms/static/js/student_account/views/account_settings_factory.js #: lms/templates/student_account/account.underscore msgid "Reset Password" -msgstr "" +msgstr "Изменить пароль" #: lms/static/js/student_account/views/account_settings_factory.js msgid "" @@ -3816,15 +3850,15 @@ msgstr "" #: lms/static/js/views/fields.js msgid "bytes" -msgstr "" +msgstr "байт" #: lms/static/js/views/fields.js msgid "KB" -msgstr "" +msgstr "КБ" #: lms/static/js/views/fields.js msgid "MB" -msgstr "" +msgstr "МБ" #: lms/static/js/views/file_uploader.js msgid "Your upload of '{file}' succeeded." @@ -4169,12 +4203,11 @@ msgid "" "<%= fileExtensions %> to upload." msgstr "" -#: cms/static/js/models/uploads.js #: lms/templates/student_account/hinted_login.underscore #: lms/templates/student_account/institution_login.underscore #: lms/templates/student_account/institution_register.underscore msgid "or" -msgstr "" +msgstr "или" #: cms/static/js/models/xblock_validation.js msgid "This component has validation issues." @@ -4240,7 +4273,7 @@ msgstr "" #: cms/static/js/models/settings/course_grading_policy.js msgid "Not able to set passing grade to less than %(minimum_grade_cutoff)s%." -msgstr "" +msgstr "Невозможно задать проходной балл ниже %(minimum_grade_cutoff)s%." #: cms/templates/js/asset-library.underscore msgid "Type" @@ -4332,11 +4365,11 @@ msgstr "" #: cms/static/js/views/content_group_item.js #: cms/static/js/views/content_group_list.js msgid "content group" -msgstr "" +msgstr "группа по изучаемым материалам" #: cms/static/js/views/content_group_list.js msgid "You have not created any content groups yet." -msgstr "" +msgstr "Вы ещё не создали ни одной группы по изучаемым материалам." #: cms/static/js/views/course_info_update.js msgid "Are you sure you want to delete this update?" @@ -4400,7 +4433,7 @@ msgstr "" #: cms/static/js/views/license.js cms/templates/js/license-selector.underscore msgid "All Rights Reserved" -msgstr "" +msgstr "Все права защищены" #: cms/static/js/views/license.js msgid "You reserve all rights for your work" @@ -4416,7 +4449,7 @@ msgstr "" #: cms/static/js/views/license.js msgid "Version" -msgstr "" +msgstr "Версия" #: cms/static/js/views/license.js msgid "Attribution" @@ -4944,6 +4977,21 @@ msgstr "" msgid "remove" msgstr "" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "Благодарим Вас! Ваш платёж получен." @@ -5026,19 +5074,15 @@ msgstr "" #: lms/templates/discovery/more_less_links.underscore msgid "MORE..." -msgstr "" +msgstr "Подробнее..." #: lms/templates/discovery/more_less_links.underscore msgid "LESS..." -msgstr "" +msgstr "Скрыть подробности..." #: lms/templates/discovery/result_item.underscore msgid "LEARN MORE" -msgstr "" - -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "" +msgstr "ПОДРОБНЕЕ" #: lms/templates/discovery/result_item.underscore msgid "Starts" @@ -5194,11 +5238,11 @@ msgstr "" #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore msgid "No Content Group" -msgstr "" +msgstr "Нет группы по изучаемым материалам" #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore msgid "Select a Content Group" -msgstr "" +msgstr "Выбрать группу по изучаемым материалам" #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore msgid "Choose a content group to associate" @@ -5210,11 +5254,11 @@ msgstr "" #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore msgid "Deleted Content Group" -msgstr "" +msgstr "Удалённая группа по изучаемым материалам" #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore msgid "Create a content group" -msgstr "" +msgstr "Создать группу по изучаемым материалам" #: lms/templates/instructor/instructor_dashboard_2/cohort-group-header.underscore msgid "(contains %(student_count)s student)" @@ -5335,7 +5379,7 @@ msgstr "" #: lms/templates/student_account/hinted_login.underscore msgid "Would you like to sign in using your %(providerName)s credentials?" -msgstr "" +msgstr "Войти с помощью логина и пароля %(providerName)s?" #: lms/templates/student_account/hinted_login.underscore msgid "Sign in using %(providerName)s" @@ -5927,10 +5971,6 @@ msgstr "" msgid "Common Problem Types" msgstr "Часто встречающиеся типы заданий" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "Добавить новый Компонент" @@ -6128,6 +6168,8 @@ msgstr "" #: cms/templates/js/content-group-editor.underscore msgid "This content group is used in one or more units." msgstr "" +"Эта группа по изучаемым материалам уже используется в одном или нескольких " +"блоках" #: cms/templates/js/course-outline.underscore msgid "Contains staff only content" @@ -6160,7 +6202,7 @@ msgstr "" #: cms/templates/js/course-outline.underscore msgid "Drag to reorder" -msgstr "" +msgstr "Перетащите для изменения порядка" #: cms/templates/js/course-outline.underscore msgid "Release Status:" @@ -6222,7 +6264,7 @@ msgstr "" #: cms/templates/js/course_grade_policy.underscore msgid "as a percent, e.g. 40" -msgstr "" +msgstr "в процентах, например, 40" #: cms/templates/js/course_grade_policy.underscore msgid "Total Number" @@ -6442,7 +6484,7 @@ msgstr "" #: cms/templates/js/license-selector.underscore msgid "Some Rights Reserved" -msgstr "" +msgstr "Некоторые права защищены" #: cms/templates/js/list.underscore msgid "Add your first %(item_type)s" diff --git a/conf/locale/zh_CN/LC_MESSAGES/django.mo b/conf/locale/zh_CN/LC_MESSAGES/django.mo index 5d9d42cf4d..c5a0aa1ac8 100644 Binary files a/conf/locale/zh_CN/LC_MESSAGES/django.mo and b/conf/locale/zh_CN/LC_MESSAGES/django.mo differ diff --git a/conf/locale/zh_CN/LC_MESSAGES/django.po b/conf/locale/zh_CN/LC_MESSAGES/django.po index 8fdd74ea32..3dda889449 100644 --- a/conf/locale/zh_CN/LC_MESSAGES/django.po +++ b/conf/locale/zh_CN/LC_MESSAGES/django.po @@ -20,6 +20,7 @@ # Wentao Han , 2013 # bnw, 2014 # bnw, 2014 +# ifLab , 2015 # Jerome Huang , 2014 # Jiadong Zhang , 2015 # Jie Li , 2013 @@ -112,7 +113,7 @@ # Hu Tong , 2014 # bnw, 2014 # bnw, 2014 -# ifLab Bistu , 2014 +# ifLab , 2014-2015 # j <786855796@qq.com>, 2015 # Jerome Huang , 2014 # Jerome Huang , 2014 @@ -245,10 +246,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:33+0000\n" +"POT-Creation-Date: 2015-07-22 17:45+0000\n" "PO-Revision-Date: 2015-06-18 03:04+0000\n" "Last-Translator: louyihua \n" -"Language-Team: Chinese (China) (http://www.transifex.com/p/edx-platform/language/zh_CN/)\n" +"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/edx-platform/language/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -266,8 +267,6 @@ msgstr "论坛" #: cms/djangoapps/contentstore/views/component.py #: lms/djangoapps/class_dashboard/dashboard_data.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Problem" msgstr "问题" @@ -276,7 +275,8 @@ msgstr "问题" msgid "Advanced" msgstr "高级" -#: cms/templates/settings.html +#: cms/djangoapps/contentstore/views/entrance_exam.py +#: lms/djangoapps/courseware/tabs.py cms/templates/settings.html msgid "Entrance Exam" msgstr "入学考试" @@ -314,7 +314,7 @@ msgstr "名称" #: cms/djangoapps/contentstore/views/videos.py #: common/lib/xmodule/xmodule/video_module/video_xfields.py msgid "Video ID" -msgstr "" +msgstr "视频 ID" #: cms/djangoapps/contentstore/views/videos.py #: common/djangoapps/config_models/admin.py @@ -346,11 +346,11 @@ msgstr "" #: common/djangoapps/config_models/admin.py msgid "Update" -msgstr "" +msgstr "更新" #: common/djangoapps/config_models/models.py msgid "Change date" -msgstr "" +msgstr "修改日期" #. Translators: this label indicates the name of the user who made this #. change: @@ -368,6 +368,55 @@ msgid "" " Please list each domain on its own line." msgstr "" +#: common/djangoapps/course_modes/admin.py +#: common/djangoapps/course_modes/models.py +#: common/lib/xmodule/xmodule/library_content_module.py +msgid "Mode" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "Verification Deadline" +msgstr "" + +#: common/djangoapps/course_modes/admin.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to submit " +"photos for verification. This appies ONLY to modes that require " +"verification." +msgstr "" + +#: common/djangoapps/course_modes/models.py +#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html +msgid "Course" +msgstr "课程" + +#: cms/templates/container.html cms/templates/library.html +msgid "Display Name" +msgstr "显示名称" + +#: common/djangoapps/course_modes/models.py +#: lms/templates/courseware/course_about.html +msgid "Price" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "Upgrade Deadline" +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: After this date/time, users will no longer be able to enroll in " +"this mode. Leave this blank if users can enroll in this mode until " +"enrollment closes for the course." +msgstr "" + +#: common/djangoapps/course_modes/models.py +msgid "" +"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external " +"ecommerce service. Leave this blank if the course has not yet been migrated" +" to the ecommerce service." +msgstr "" + #: common/djangoapps/course_modes/models.py msgid "Honor Code Certificate" msgstr "诚信准则证书" @@ -727,8 +776,8 @@ msgstr "" #: common/djangoapps/student/views.py msgid "" -"If you don't have an {platform_name} account yet, click Register " -"Now at the top of the page." +"If you don't have an {platform_name} account yet, click " +"Register at the top of the page." msgstr "" #: common/djangoapps/student/views.py @@ -1678,10 +1727,6 @@ msgstr "无法将“{given_answer}”解析为一个数字。" msgid "XML data for the annotation" msgstr "用于批注的XML数据" -#: cms/templates/container.html cms/templates/library.html -msgid "Display Name" -msgstr "显示名称" - #: common/lib/xmodule/xmodule/annotatable_module.py #: common/lib/xmodule/xmodule/discussion_module.py #: common/lib/xmodule/xmodule/html_module.py @@ -1798,9 +1843,8 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py msgid "" -"Defines how often inputs are randomized when a student loads the problem. " -"This setting only applies to problems that can have randomly generated " -"numeric values. A default value can be set in Advanced Settings." +"Defines when to randomize the variables specified in the associated Python " +"script. For problems that do not randomize values, specify \"Never\". " msgstr "" #: common/lib/xmodule/xmodule/capa_base.py @@ -3175,10 +3219,6 @@ msgstr "" msgid "Library Version" msgstr "" -#: common/lib/xmodule/xmodule/library_content_module.py -msgid "Mode" -msgstr "" - #: common/lib/xmodule/xmodule/library_content_module.py msgid "Determines how content is drawn from the library" msgstr "" @@ -3741,12 +3781,12 @@ msgstr "" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "" -"Specify how often variable values in a problem are randomized when a student" -" loads the problem. Valid values are \"always\", \"onreset\", \"never\", and" -" \"per_student\". This setting only applies to problems that have randomly " -"generated numeric values." +"Specify the default for how often variable values in a problem are " +"randomized. This setting should be set to \"never\" unless you plan to " +"provide a Python script to identify and randomize values in most of the " +"problems in your course. Valid values are \"always\", \"onreset\", " +"\"never\", and \"per_student\"." msgstr "" -"指定当学生加载一个问题时,该问题中变量值随机化的频繁程度,有效值为“always”,“onreset”,“never”或“per_student”。该设置只对含有随机生成数值的问题有效。" #: common/lib/xmodule/xmodule/modulestore/inheritance.py msgid "Days Early for Beta Users" @@ -4749,7 +4789,7 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor/views/legacy.py #: lms/djangoapps/instructor/views/tools.py -#: lms/djangoapps/instructor_task/tasks_helper.py lms/templates/dashboard.html +#: lms/djangoapps/instructor_task/tasks_helper.py #: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Username" @@ -4862,6 +4902,34 @@ msgstr "" msgid "Visit a course wiki to add an article." msgstr "浏览课程维基添加课程标题" +#: lms/djangoapps/courseware/access_response.py +msgid "Course does not start until {}" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You have unfulfilled milestones" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You do not have access to this course on a mobile device" +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"There is no user with the username or email address {user_name} enrolled in " +"this course." +msgstr "" + +#: lms/djangoapps/courseware/masquerade.py +msgid "" +"This type of component cannot be shown while viewing the course as a " +"specific student." +msgstr "" + #: lms/djangoapps/courseware/tabs.py #: lms/templates/courseware/courseware-error.html msgid "Courseware" @@ -5491,7 +5559,6 @@ msgstr "性别" #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/tasks_helper.py -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Level of Education" msgstr "教育水平" @@ -5511,28 +5578,22 @@ msgstr "群组" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your enrolled student profile report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." +"The enrolled learner profile report is being created. To view the status of " +"the report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An enrolled student profile 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." +"This enrollment report is currently being created. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your students who may enroll report is being generated! You can view the " -"status of the generation task in the 'Pending Tasks' section." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "" -"A students who may enroll 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." +"The enrollment report is being created. This report contains information " +"about learners who can enroll in the course. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5591,29 +5652,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your detailed enrollment report is being generated! You can view the status " -"of the generation task in the 'Pending Tasks' section." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A detailed enrollment 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." +"The detailed enrollment report is being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your executive summary report is being created. To view the status of the " -"report, see the 'Pending Tasks' section." +"The executive summary report is being created. To view the status of the " +"report, see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"An executive summary report is currently in progress. To view the status of " -"the report, see the 'Pending Tasks' section. When completed, the report will" -" be available for download in the table below. You will be able to download " -"the report when it is complete." +"The executive summary report is currently being created. To view the status " +"of the report, see Pending Instructor Tasks below. You will be able to " +"download the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5667,28 +5727,28 @@ msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your grade report is being generated! You can view the status of the " -"generation task in the 'Pending Tasks' section." +"The grade report is being created. To view the status of the report, see " +"Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A grade 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." +"The grade report is currently being created. To view the status of the " +"report, see Pending Instructor Tasks below. You will be able to download the" +" report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"Your problem grade report is being generated! You can view the status of the" -" generation task in the 'Pending Tasks' section." +"The problem grade report is being created. To view the status of the report," +" see Pending Instructor Tasks below." msgstr "" #: lms/djangoapps/instructor/views/api.py msgid "" -"A problem grade report is already being generated. Check the 'Pending Tasks'" -" table for the status of the task. When completed, the report will be " -"available for download in the table below." +"A problem grade report is already being generated. To view the status of the" +" report, see Pending Instructor Tasks below. You will be able to download " +"the report when it is complete." msgstr "" #: lms/djangoapps/instructor/views/api.py @@ -5820,13 +5880,12 @@ msgid "Data Download" msgstr "数据下载" #: lms/djangoapps/instructor/views/instructor_dashboard.py -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Analytics" -msgstr "分析" +msgid "For analytics about your course, go to {analytics_dashboard_name}." +msgstr "" #: lms/djangoapps/instructor/views/instructor_dashboard.py -msgid "Demographic data is now available in {dashboard_link}." -msgstr "统计数据现已可通过{dashboard_link}查看。" +msgid "Analytics" +msgstr "分析" #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Metrics" @@ -6093,7 +6152,6 @@ msgid "Title" msgstr "标题" #: lms/templates/register.html -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html msgid "Year of Birth" msgstr "出生年份" @@ -6701,10 +6759,6 @@ msgstr "评论" msgid "University" msgstr "大学" -#: lms/djangoapps/shoppingcart/reports.py cms/templates/widgets/header.html -msgid "Course" -msgstr "课程" - #: lms/djangoapps/shoppingcart/reports.py msgid "Course Announce Date" msgstr "课程发布日期" @@ -7455,6 +7509,10 @@ msgstr "" msgid "course_id must be provided" msgstr "" +#: lms/djangoapps/teams/views.py +msgid "The supplied topic id {topic_id} is not valid" +msgstr "" + #: lms/djangoapps/teams/views.py msgid "text_search is not yet supported." msgstr "" @@ -7464,11 +7522,11 @@ msgid "last_activity is not yet supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The supplied course_id {course_id} is not valid." +msgid "The ordering {} is not supported" msgstr "" #: lms/djangoapps/teams/views.py -msgid "The ordering {} is not supported" +msgid "The supplied course_id {course_id} is not valid." msgstr "" #: lms/djangoapps/teams/views.py @@ -7521,6 +7579,16 @@ msgstr "" msgid "There was an error verifying your ID photos." msgstr "在验证你身份证件的照片时发生了一个错误。" +#: lms/djangoapps/verify_student/models.py +msgid "The course for which this deadline applies" +msgstr "" + +#: lms/djangoapps/verify_student/models.py +msgid "" +"The datetime after which users are no longer allowed to submit photos for " +"verification." +msgstr "" + #: lms/djangoapps/verify_student/views.py msgid "Intro" msgstr "" @@ -8333,6 +8401,10 @@ msgstr "必须存在一个可以将学生自动分配进去的群组。" msgid "A cohort with the same name already exists." msgstr "具有相同名称的群组已存在。" +#: openedx/core/djangoapps/credit/email_utils.py +msgid "Course Credit Eligibility" +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "" "Unique identifier for this credit provider. Only alphanumeric characters and" @@ -8380,6 +8452,20 @@ msgid "" "credit provider." msgstr "" +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"eligibility email content which is sent when user has met all credit " +"eligibility requirements." +msgstr "" + +#: openedx/core/djangoapps/credit/models.py +msgid "" +"Plain text or html content for displaying custom message inside credit " +"receipt email content which is sent *after* paying to get credit for a " +"credit course." +msgstr "" + #: openedx/core/djangoapps/credit/models.py msgid "Deadline for purchasing and requesting credit." msgstr "" @@ -8972,9 +9058,7 @@ msgstr "页面无法找到" #: cms/templates/asset_index.html cms/templates/certificates.html #: cms/templates/container.html cms/templates/course_outline.html #: cms/templates/group_configurations.html cms/templates/library.html -#: lms/templates/courseware/courses.html -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courses.html lms/templates/edxnotes/edxnotes.html #: lms/templates/instructor/instructor_dashboard_2/metrics.html #: lms/templates/student_profile/learner_profile.html msgid "Loading" @@ -9110,6 +9194,11 @@ msgstr "访问你的{link_start}课程面板{link_end}来查看课程。" msgid "Course Navigation" msgstr "课程导航" +#: cms/templates/widgets/header.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html +msgid "Account" +msgstr "" + #: cms/templates/widgets/header.html lms/templates/help_modal.html #: lms/templates/static_templates/help.html wiki/plugins/help/wiki_plugin.py msgid "Help" @@ -9270,7 +9359,8 @@ msgstr "了解更多" msgid "Starts" msgstr "开始" -#: lms/templates/dashboard.html +#: lms/templates/dashboard.html lms/templates/navigation-edx.html +#: lms/templates/navigation.html msgid "Dashboard" msgstr "课程面板" @@ -9299,12 +9389,12 @@ msgid "Clear search" msgstr "清空搜索结果" #: lms/templates/dashboard.html -msgid "Want to change your account settings?" -msgstr "想要更改你的账户设置?" +msgid "Find New Courses" +msgstr "" #: lms/templates/dashboard.html -msgid "Click the arrow next to your username above." -msgstr "单击上方你用户名旁边的箭头。" +msgid "Account Status Info" +msgstr "" #: lms/templates/dashboard.html msgid "Order History" @@ -9893,27 +9983,23 @@ msgid "More options dropdown" msgstr "更多选择下拉列表" #: lms/templates/navigation-edx.html lms/templates/navigation.html -#: lms/templates/student_account/account_settings.html -msgid "Account Settings" -msgstr "账户设置" - -#: lms/templates/navigation-edx.html lms/templates/navigation.html -msgid "My Profile" -msgstr "我的用户资料" +msgid "Profile" +msgstr "" #: lms/templates/navigation-edx.html lms/templates/navigation.html #: lms/templates/shoppingcart/shopping_cart.html msgid "Shopping Cart" msgstr "购物车" -#: lms/templates/navigation-edx.html lms/templates/register.html -msgid "Register" -msgstr "注册" - #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "Sign in" msgstr "登录" +#: lms/templates/navigation-edx.html lms/templates/navigation.html +#: lms/templates/register.html +msgid "Register" +msgstr "注册" + #: lms/templates/navigation-edx.html lms/templates/navigation.html msgid "" "Warning: Your browser is not fully supported. We strongly " @@ -9933,10 +10019,6 @@ msgstr "系统管理员" msgid "Schools" msgstr "学校" -#: lms/templates/navigation.html -msgid "Register Now" -msgstr "现在注册" - #: lms/templates/notes.html lms/templates/textannotation.html #: lms/templates/videoannotation.html msgid "You do not have any notes." @@ -10480,12 +10562,12 @@ msgstr "Git动作" #. Translators: git is a version-control system; see http://git-scm.com/about #: lms/templates/sysadmin_dashboard_gitlogs.html msgid "No git import logs have been recorded." -msgstr "" +msgstr "没有git导入日志被记录。" #. Translators: git is a version-control system; see http://git-scm.com/about #: lms/templates/sysadmin_dashboard_gitlogs.html msgid "No git import logs have been recorded for this course." -msgstr "" +msgstr "此课程没有git导入日志被记录。" #: lms/templates/textannotation.html msgid "Source:" @@ -10946,6 +11028,11 @@ msgstr "" msgid "I completed the {course_title} course on {platform_name}." msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +msgid "" +"I completed a course on {platform_name}. Take a look at my certificate." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Click the link to see my certificate." msgstr "" @@ -10954,6 +11041,15 @@ msgstr "" msgid "Post on Facebook" msgstr "" +#: lms/templates/certificates/_accomplishment-banner.html +#: lms/templates/dashboard/_dashboard_course_listing.html +msgid "Share on Twitter" +msgstr "" + +#: lms/templates/certificates/_accomplishment-banner.html +msgid "Tweet this Accomplishment. Pop up window." +msgstr "" + #: lms/templates/certificates/_accomplishment-banner.html msgid "Add to LinkedIn Profile" msgstr "" @@ -11196,6 +11292,10 @@ msgstr "{chapter}, 当前章节" msgid "due {date}" msgstr "到期日{date}" +#: lms/templates/courseware/accordion.html +msgid "This section is graded." +msgstr "" + #: lms/templates/courseware/course_about.html #: lms/templates/courseware/mktg_course_about.html msgid "An error occurred. Please try again later." @@ -11296,10 +11396,6 @@ msgstr "课程结束" msgid "Estimated Effort" msgstr "预期课程目标" -#: lms/templates/courseware/course_about.html -msgid "Price" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Prerequisites" msgstr "预备知识" @@ -11328,12 +11424,24 @@ msgstr "" msgid "View this course as:" msgstr "查看课程的身份:" +#: lms/templates/courseware/course_navigation.html +msgid "Specific student" +msgstr "" + #: lms/templates/courseware/course_navigation.html msgid "Student in {content_group}" msgstr "" #: lms/templates/courseware/course_navigation.html -msgid "set preview mode" +msgid "Username or email:" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "Set preview mode" +msgstr "" + +#: lms/templates/courseware/course_navigation.html +msgid "You are now viewing the course as {user_name}." msgstr "" #: lms/templates/courseware/course_navigation.html @@ -11368,6 +11476,10 @@ msgstr "" msgid "{platform_name} Logo" msgstr "" +#: lms/templates/courseware/courses.html +msgid "List of Courses" +msgstr "" + #: lms/templates/courseware/courses.html msgid "Refine your search" msgstr "" @@ -11633,74 +11745,6 @@ msgstr "" msgid "To send email, visit the Email section of the Instructor Dashboard." msgstr "" -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "No Analytics are available at this time." -msgstr "目前没有可用的分析数据" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Student activity day by day" -msgstr "学生的日常活动" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Day" -msgstr "日" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/shoppingcart/receipt.html -msgid "Students" -msgstr "学生" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Score distribution for problems" -msgstr "问答问题的成绩分布" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Max" -msgstr "最大" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Points Earned (Num Students)" -msgstr "得分(学生数目)" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There is no data available to display at this time." -msgstr "目前没有可用的数据" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Loading the latest graphs for you; depending on your class size, this may " -"take a few minutes." -msgstr "正在为您加载最新统计图,因班级学员人数规模的差异,这个过程可能要花几分钟。" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Count of Students that Opened a Subsection" -msgstr "统计开辟了子栏目的学生人数" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "Grade Distribution per Problem" -msgstr "每个问题的成绩分布" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -#: lms/templates/instructor/instructor_dashboard_2/metrics.html -msgid "There are no problems in this section." -msgstr "本章没有问题" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Students answering correctly" -msgstr "回答正确的学生" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "Number of students" -msgstr "学生数目" - -#: lms/templates/courseware/legacy_instructor_dashboard.html -msgid "" -"Student distribution per country, all courses, Sep 12 to Oct 17, 1 server " -"(shown here as an example):" -msgstr "" - #: lms/templates/courseware/legacy_instructor_dashboard.html msgid "Pending Instructor Tasks" msgstr "等待主讲教师处理" @@ -11867,11 +11911,12 @@ msgid "Requirements for Course Credit" msgstr "" #: lms/templates/courseware/progress.html -msgid "You are no longer eligible for this course." +msgid "{student_name}, you are no longer eligible for credit in this course." msgstr "" #: lms/templates/courseware/progress.html -msgid "You have met the requirements for credit in this course." +msgid "" +"{student_name}, you have met the requirements for credit in this course." msgstr "" #: lms/templates/courseware/progress.html @@ -11936,6 +11981,46 @@ msgid "" "another section on the left." msgstr "您最近在{section_link}。如果您已经完成此章节,请选择左侧的另一个章节。" +#: lms/templates/credit_notifications/credit_eligibility_email.html +#: lms/templates/emails/business_order_confirmation_email.txt +#: lms/templates/emails/order_confirmation_email.txt +msgid "Hi {name}," +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Congratulations! You are eligible to receive university credit from edX " +"partners! Click {link} to get your credit now." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"Credit from can help you get a jump start on your university degree, finish " +"a degree already started, or fulfill requirements at a different academic " +"institution." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"To get university credit for {course_name}, simply go to your {link} and " +"click the yellow \"Get Credit\" button. No application, transcript, or grade" +" report is required." +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "" +"We hope you enjoyed the course, and we hope to see you in future edX " +"courses!" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "The edX team" +msgstr "" + +#: lms/templates/credit_notifications/credit_eligibility_email.html +msgid "Find more edX courses you can take for university credit." +msgstr "" + #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "" "Final course details are being wrapped up at this time. Your final standing " @@ -12055,10 +12140,6 @@ msgstr "" msgid "I'm learning on {platform_name}:" msgstr "" -#: lms/templates/dashboard/_dashboard_course_listing.html -msgid "Share on Twitter" -msgstr "" - #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Course options dropdown" msgstr "" @@ -12950,11 +13031,6 @@ msgstr "该邮件是由 {site_name} 向 {email_address} 自动发出的" msgid "You have been invited to a beta test for {course_name}" msgstr "你已被邀请成为 {course_name} 的一名 Beta 测试员。" -#: lms/templates/emails/business_order_confirmation_email.txt -#: lms/templates/emails/order_confirmation_email.txt -msgid "Hi {name}," -msgstr "" - #: lms/templates/emails/business_order_confirmation_email.txt msgid "Thank you for your purchase of " msgstr "" @@ -13703,7 +13779,7 @@ msgstr "分数线:" msgid "" "View detailed Git import logs for this course {link_start}by clicking " "here{link_end}." -msgstr "" +msgstr "查看本课程的详细Git导入日志,请点击{link_start}这里{link_end}。" #: lms/templates/instructor/instructor_dashboard_2/course_info.html msgid "Course Warnings" @@ -14368,30 +14444,6 @@ msgstr "" msgid "Send me a copy of the invoice" msgstr "" -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Score Distribution" -msgstr "成绩分布" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"The chart below displays the score distribution for each standard problem in" -" your class, specified by the problem's url name." -msgstr "下图显示的是您的班级中每个问答的成绩分布,问答由其链接地址指定。" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "" -"Scores are shown without weighting applied, so if your problem contains 2 " -"questions, it will display as having a total of 2 points." -msgstr "所显示的成绩尚未加权,所以,如果您的问答包含2个问题,系统显示的总分为2分。" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Loading problem list..." -msgstr "加载问题列表……" - -#: lms/templates/instructor/instructor_dashboard_2/instructor_analytics.html -msgid "Gender Distribution" -msgstr "性别分布" - #: lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html msgid "Instructor Dashboard" msgstr "教师面板" @@ -14610,6 +14662,10 @@ msgstr "" msgid "Add CCX Coach" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There is no data available to display at this time." +msgstr "目前没有可用的数据" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Use Reload Graphs to refresh the graphs." msgstr "" @@ -14658,6 +14714,10 @@ msgstr "" msgid "Download Problem Data for all Problems as a CSV" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "Grade Distribution per Problem" +msgstr "每个问题的成绩分布" + #: lms/templates/instructor/instructor_dashboard_2/metrics.html msgid "Download Student Opened as a CSV" msgstr "以CSV格式下载学生开放数据" @@ -14670,6 +14730,10 @@ msgstr "以CSV格式下载学生成绩数据" msgid "This is a partial list, to view all students download as a csv." msgstr "这是一个部分列表,查看所有以CSV格式下载的学生信息" +#: lms/templates/instructor/instructor_dashboard_2/metrics.html +msgid "There are no problems in this section." +msgstr "本章没有问题" + #: lms/templates/instructor/instructor_dashboard_2/send_email.html msgid "Send Email" msgstr "发送电子邮件" @@ -15430,6 +15494,10 @@ msgstr "" msgid "Discount Applied:" msgstr "" +#: lms/templates/shoppingcart/receipt.html +msgid "Students" +msgstr "学生" + #. Translators: Please keep the "" and "" tags around your #. translation of the word "this" in your translation. #: lms/templates/shoppingcart/receipt.html @@ -15665,6 +15733,10 @@ msgstr "请等待几秒钟后再刷新该页面。如果问题照旧,请向{em msgid "Currently the {platform_name} servers are overloaded" msgstr " 目前{platform_name}平台的服务器已经超负荷" +#: lms/templates/student_account/account_settings.html +msgid "Account Settings" +msgstr "账户设置" + #: lms/templates/student_account/finish_auth.html msgid "Please Wait" msgstr "" @@ -15768,15 +15840,25 @@ msgstr "在编辑你的名字时出现下面的错误:" msgid "Re-Verify for {course_name}" msgstr "" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html msgid "Verification Deadline Has Passed" msgstr "认证期限已过" -#: lms/templates/verify_student/missed_verification_deadline.html +#: lms/templates/verify_student/missed_deadline.html +msgid "Upgrade Deadline Has Passed" +msgstr "" + +#: lms/templates/verify_student/missed_deadline.html msgid "" -"The verification deadline for {course_name} was {date}. Verification is no " +"The verification deadline for {course_name} was {date}. Verification is no " "longer available." -msgstr "{course_name}的认证期限是{date},认证功能已不可用。" +msgstr "" + +#: lms/templates/verify_student/missed_deadline.html +msgid "" +"The deadline to upgrade to a verified certificate for this course has " +"passed. You can still earn an honor code certificate." +msgstr "" #: lms/templates/verify_student/pay_and_verify.html msgid "Upgrade Your Enrollment For {course_name}." @@ -18780,10 +18862,6 @@ msgstr "导出" msgid "Current Library:" msgstr "当前知识库:" -#: cms/templates/widgets/header.html -msgid "Account" -msgstr "账户" - #: cms/templates/widgets/header.html msgid "Account Navigation" msgstr "账户导航" diff --git a/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo b/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo index 155eb3553d..0e6f43329c 100644 Binary files a/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo and b/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/zh_CN/LC_MESSAGES/djangojs.po b/conf/locale/zh_CN/LC_MESSAGES/djangojs.po index 5c8ecf54b1..288b35c810 100644 --- a/conf/locale/zh_CN/LC_MESSAGES/djangojs.po +++ b/conf/locale/zh_CN/LC_MESSAGES/djangojs.po @@ -123,10 +123,10 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2015-07-13 04:31+0000\n" -"PO-Revision-Date: 2015-07-10 19:12+0000\n" +"POT-Creation-Date: 2015-07-22 17:43+0000\n" +"PO-Revision-Date: 2015-07-14 14:36+0000\n" "Last-Translator: Sarina Canelake \n" -"Language-Team: Chinese (China) (http://www.transifex.com/p/edx-platform/language/zh_CN/)\n" +"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/edx-platform/language/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2328,14 +2328,31 @@ msgstr "标签:" msgid "name" msgstr "名称" +#: lms/djangoapps/teams/static/teams/js/collections/team.js +msgid "open_slots" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/collections/topic.js msgid "team count" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/team_card.js +msgid "%(member_count)s / %(max_member_count)s Member" +msgid_plural "%(member_count)s / %(max_member_count)s Members" +msgstr[0] "" + +#: 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/teams.js +msgid "Create new team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" -"Course teams are organized into topics created by course instructors. Try to" -" join others in an existing team before you decide to create a new team!" +"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 @@ -2350,6 +2367,14 @@ msgstr "" msgid "Browse" msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The page \"%(route)s\" could not be found." +msgstr "" + +#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js +msgid "The topic \"%(topic)s\" could not be found." +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "%(team_count)s Team" msgid_plural "%(team_count)s Teams" @@ -2401,22 +2426,6 @@ msgstr "生成评分结果错误,请重试。" msgid "Error generating problem grade report. Please try again." msgstr "" -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Unavailable metric display." -msgstr "公制显示不可用。" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Error fetching grade distributions." -msgstr "获取成绩分布错误。" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "Last Updated: <%= timestamp %>" -msgstr "最近更新时间:<%= timestamp %>" - -#: lms/static/coffee/src/instructor_dashboard/instructor_analytics.js -msgid "<%= num_students %> students scored." -msgstr "<%= num_students %>学员已判分。" - #: lms/static/coffee/src/instructor_dashboard/membership.js #: lms/static/js/student_account/views/account_settings_factory.js #: lms/static/js/student_profile/views/learner_profile_factory.js @@ -3170,6 +3179,11 @@ msgstr "您的捐款无法提交。" msgid "An error occurred. Please try again later." msgstr "出现了未知错误,请稍后重试。" +#: lms/static/js/discovery/form.js +msgid "Viewing %s course" +msgid_plural "Viewing %s courses" +msgstr[0] "" + #: lms/static/js/discovery/form.js msgid "We couldn't find any results for \"%s\"." msgstr "" @@ -3182,13 +3196,29 @@ msgstr "出错了,请尝试重新搜素。" msgid "Focus grabber" msgstr "焦点采集器" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js #: lms/static/js/edxnotes/views/search_box.js -#: lms/static/js/edxnotes/views/toggle_notes_factory.js msgid "" "An error has occurred. Make sure that you are connected to the Internet, and" " then try refreshing the page." msgstr "出现了一个错误。请确保你已联网,然后刷新页面。" +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Hide notes" +msgstr "隐藏注释" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes visible" +msgstr "注释可见" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Show notes" +msgstr "显示注释" + +#: lms/static/js/edxnotes/views/notes_visibility_factory.js +msgid "Notes hidden" +msgstr "注释已隐藏" + #: lms/static/js/edxnotes/views/search_box.js msgid "" "Please enter a term in the %(anchor_start)s search field%(anchor_end)s." @@ -3198,22 +3228,6 @@ msgstr "请在 %(anchor_start)s 搜索字段%(anchor_end)s输入一个关键词 msgid "Current tab" msgstr "当前选项" -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Hide notes" -msgstr "隐藏注释" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes visible" -msgstr "注释可见" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Show notes" -msgstr "显示注释" - -#: lms/static/js/edxnotes/views/toggle_notes_factory.js -msgid "Notes hidden" -msgstr "注释已隐藏" - #: lms/static/js/edxnotes/views/tabs/course_structure.js msgid "Location in Course" msgstr "课程中的位置" @@ -4923,6 +4937,21 @@ msgstr "全部移除" msgid "remove" msgstr "移除" +#: lms/templates/commerce/provider.underscore +#: lms/templates/discovery/result_item.underscore +msgid "gettext(" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "%s" +msgstr "" + +#: lms/templates/commerce/provider.underscore +msgid "" +"" +msgstr "" + #: lms/templates/commerce/receipt.underscore msgid "Thank you! We have received your payment." msgstr "" @@ -5015,10 +5044,6 @@ msgstr "" msgid "LEARN MORE" msgstr "" -#: lms/templates/discovery/result_item.underscore -msgid "gettext(" -msgstr "" - #: lms/templates/discovery/result_item.underscore msgid "Starts" msgstr "" @@ -5904,10 +5929,6 @@ msgstr "" msgid "Common Problem Types" msgstr "常见问题类型" -#: cms/templates/js/add-xblock-component-menu-problem.underscore -msgid "Common Problems with Hints and Feedback" -msgstr "" - #: cms/templates/js/add-xblock-component.underscore msgid "Add New Component" msgstr "添加新组件" diff --git a/docs/en_us/platform_api/source/conf.py b/docs/en_us/platform_api/source/conf.py index 8ebe9c953d..d929c6a560 100644 --- a/docs/en_us/platform_api/source/conf.py +++ b/docs/en_us/platform_api/source/conf.py @@ -183,7 +183,13 @@ MOCK_MODULES = [ 'update_account_settings', 'serializers', 'profile_images.images', - 'xmodule.course_module' + 'xmodule.course_module', + 'user_api.accounts.api', + 'user_api.accounts.serializers', + 'ecommerce_api_client', + 'client', + 'ecommerce_api_client.client', + 'ecommerce_api_client.exceptions' ] diff --git a/docs/en_us/platform_api/source/course_structure/endpoints.rst b/docs/en_us/platform_api/source/course_structure/endpoints.rst deleted file mode 100644 index fa96bc08dd..0000000000 --- a/docs/en_us/platform_api/source/course_structure/endpoints.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. _EdX Platform Course Structure API Endpoints: - -################################################ -Course Structure API Endpoints -################################################ - -You use the Course Structure API to view information about -courses. - -The following tasks and endpoints are currently supported. - - -.. list-table:: - :widths: 10 70 - :header-rows: 1 - - * - To: - - Use this endpoint: - * - :ref:`Get a list of courses in the edX platform ` - - GET /api/course_structure/v0/courses/ - * - :ref:`Get details about a course ` - - GET /api/course_structure/v0/courses/{course_id}/ - * - :ref:`Get a course's structure, or blocks ` - - GET /api/course_structure/v0/course_structures/{course_id}/ - * - :ref:`Get a course's grading policy ` - - GET /api/course_structure/v0/grading_policies/{course_id}/ - \ No newline at end of file diff --git a/docs/en_us/platform_api/source/course_structure/index.rst b/docs/en_us/platform_api/source/course_structure/index.rst index 0aa08224af..46b68d230d 100644 --- a/docs/en_us/platform_api/source/course_structure/index.rst +++ b/docs/en_us/platform_api/source/course_structure/index.rst @@ -8,5 +8,4 @@ Course Structure API Version 0 :maxdepth: 2 overview - endpoints course_structure diff --git a/docs/en_us/platform_api/source/course_structure/overview.rst b/docs/en_us/platform_api/source/course_structure/overview.rst index 099f362359..ab8e5b7fdc 100644 --- a/docs/en_us/platform_api/source/course_structure/overview.rst +++ b/docs/en_us/platform_api/source/course_structure/overview.rst @@ -16,16 +16,24 @@ significant enhancements to this API. Currently the Course Structure API is for internal use only; third parties cannot use the API to access course structure data. -*********************************************** -Course Structure API Capabilities -*********************************************** +********************************************** +Course Structure API Resources and Endpoints +********************************************** -With the Course Structure API, you can complete these tasks. +The Course Structure API supports the following resources, tasks, methods, and +endpoints. -* :ref:`Get a list of courses in the edX platform ` +.. list-table:: + :widths: 10 70 + :header-rows: 1 -* :ref:`Get details about a course ` - -* :ref:`Get a course's structure, or blocks ` - -* :ref:`Get a course's grading policy ` + * - To: + - Use this endpoint: + * - :ref:`Get a list of courses in the edX platform ` + - GET /api/course_structure/v0/courses/ + * - :ref:`Get details about a course ` + - GET /api/course_structure/v0/courses/{course_id}/ + * - :ref:`Get a course's structure, or blocks ` + - GET /api/course_structure/v0/course_structures/{course_id}/ + * - :ref:`Get a course's grading policy ` + - GET /api/course_structure/v0/grading_policies/{course_id}/ diff --git a/docs/en_us/platform_api/source/enrollment/endpoints.rst b/docs/en_us/platform_api/source/enrollment/endpoints.rst deleted file mode 100644 index 377d1be4db..0000000000 --- a/docs/en_us/platform_api/source/enrollment/endpoints.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _edX Enrollment API Endpoints: - -################################################ -Enrollment API Endpoints -################################################ - -You use the Enrollment API to view information about users and -their course enrollments, course information, and videos and transcripts. - -The following tasks and endpoints are currently supported. - - -.. list-table:: - :widths: 10 70 - :header-rows: 1 - - * - To: - - Use this endpoint: - * - :ref:`Get the user's enrollment status in a course ` - - /api/enrollment/v1/enrollment/{user_id},{course_id} - * - :ref:`Get enrollment details for a course` - - /api/enrollment/v1/course/{course_id} - * - :ref:`View a user's enrollments ` - - /api/enrollment/v1/enrollment - * - :ref:`Enroll a user in a course ` - - /api/enrollment/v1/enrollment{“course_details”:{“course_id”:“*course_id*”}} \ No newline at end of file diff --git a/docs/en_us/platform_api/source/enrollment/enrollment.rst b/docs/en_us/platform_api/source/enrollment/enrollment.rst index 717498674a..97395ffe9d 100644 --- a/docs/en_us/platform_api/source/enrollment/enrollment.rst +++ b/docs/en_us/platform_api/source/enrollment/enrollment.rst @@ -1,14 +1,18 @@ -################################################## -Enrollment API -################################################## +################################### +Enrollment API Enrollment Resource +################################### -This page contains information on using the Enrollment API to complete -the following actions. +With the Enrollment API **Enrollment** resource, you can complete the +following tasks. -* :ref:`Get the user's enrollment status in a course ` -* :ref:`Get enrollment details for a course` -* :ref:`View a user's enrollments ` -* :ref:`Enroll a user in a course ` +* :ref:`Get the user's enrollment status in a course `. +* :ref:`Get the user's enrollment information for a course`. +* :ref:`View a user's enrollments `. +* :ref:`Enroll a user in a course `. .. _Get the Users Enrollment Status in a Course: @@ -33,37 +37,34 @@ Get the User's Enrollment Status in a Course "mode": "honor", "is_active": true, "course_details": { - "course_end": "2015-06-30T05:00:00Z", - "course_start": "2015-02-05T05:00:00Z", - "course_modes": [ - { - "slug": "honor", - "name": "Honor Code Certificate", - "min_price": 0, - "suggested_prices": [], - "currency": "usd", - "expiration_datetime": null, - "description": null, - "sku": null - } - ], - "enrollment_start": "2015-01-01T05:00:00Z", - "enrollment_end": "2015-02-13T05:00:00Z", - "invite_only": false, - "course_id": "edX/DemoX/Demo_Course" - }, - "user": "staff" + "course_id": "edX/DemoX/Demo_Course", + "enrollment_end": null, + "course_modes": [ + { + "slug": "honor", + "name": "Honor Code Certificate", + "min_price": 0, + "suggested_prices": [], + "currency": "usd", + "expiration_datetime": null, + "description": null + } + ], + "enrollment_start": null, + "invite_only": false + }, + "user": "staff" } .. _Get Enrollment Details for a Course: -************************************ -Get Enrollment Details for a Course -************************************ +************************************************** +Get the User's Enrollment Information for a Course +************************************************** .. autoclass:: enrollment.views.EnrollmentCourseDetailView -**Example response showing a user's course enrollments** +**Example response showing a user's course enrollment information** .. code-block:: json @@ -73,8 +74,8 @@ Get Enrollment Details for a Course Allow: GET, HEAD, OPTIONS { - "course_end": "2015-06-30T05:00:00Z", - "course_start": "2015-02-05T05:00:00Z", + "course_id": "edX/DemoX/Demo_Course", + "enrollment_end": null, "course_modes": [ { "slug": "honor", @@ -83,27 +84,24 @@ Get Enrollment Details for a Course "suggested_prices": [], "currency": "usd", "expiration_datetime": null, - "description": null, - "sku": null + "description": null } ], - "enrollment_start": "2015-01-01T05:00:00Z", - "enrollment_end": "2015-02-13T05:00:00Z", - "invite_only": false, - "course_id": "edX/DemoX/Demo_Course" + "enrollment_start": null, + "invite_only": false } .. _View and add to a Users Course Enrollments: -********************************************* -View and Add to a User's Course Enrollments -********************************************* +********************************************************** +View a User's Enrollments or Enroll a User in a Course +********************************************************** .. autoclass:: enrollment.views.EnrollmentListView -**Example response showing a user's course enrollments** +**Example response showing a user who is enrolled in two courses** .. code-block:: json @@ -114,12 +112,12 @@ View and Add to a User's Course Enrollments [ { - "created": "2014-11-19T04:06:55Z", + "created": "2014-09-19T18:08:37Z", "mode": "honor", "is_active": true, "course_details": { - "course_end": "2015-06-30T05:00:00Z", - "course_start": "2015-02-05T05:00:00Z", + "course_id": "edX/DemoX/Demo_Course", + "enrollment_end": null, "course_modes": [ { "slug": "honor", @@ -128,21 +126,41 @@ View and Add to a User's Course Enrollments "suggested_prices": [], "currency": "usd", "expiration_datetime": null, - "description": null, - "sku": null + "description": null } ], - "enrollment_start": "2015-01-01T05:00:00Z", - "enrollment_end": "2015-02-13T05:00:00Z", - "invite_only": false, - "course_id": "edX/DemoX/Demo_Course" + "enrollment_start": null, + "invite_only": false + }, + "user": "honor" }, - "user": "staff" - } + { + "created": "2014-09-19T18:09:35Z", + "mode": "honor", + "is_active": true, + "course_details": { + "course_id": "ArbisoftX/BulkyEmail101/2014-15", + "enrollment_end": null, + "course_modes": [ + { + "slug": "honor", + "name": "Honor Code Certificate", + "min_price": 0, + "suggested_prices": [], + "currency": "usd", + "expiration_datetime": null, + "description": null + } + ], + "enrollment_start": "2014-05-01T04:00:00Z", + "invite_only": false + }, + "user": "honor" + } ] -**Example post request to enroll the user in a new course** +**Example response showing that a user has been enrolled in a new course** .. code-block:: json diff --git a/docs/en_us/platform_api/source/enrollment/index.rst b/docs/en_us/platform_api/source/enrollment/index.rst index 2bf03fdb5c..8ee8dba5f6 100644 --- a/docs/en_us/platform_api/source/enrollment/index.rst +++ b/docs/en_us/platform_api/source/enrollment/index.rst @@ -8,5 +8,4 @@ Enrollment API Version 1.0 :maxdepth: 2 overview - endpoints enrollment diff --git a/docs/en_us/platform_api/source/enrollment/overview.rst b/docs/en_us/platform_api/source/enrollment/overview.rst index 742c50aaa1..7e219dee20 100644 --- a/docs/en_us/platform_api/source/enrollment/overview.rst +++ b/docs/en_us/platform_api/source/enrollment/overview.rst @@ -5,30 +5,45 @@ Enrollment API Overview ################################################ Use the Enrollment API to view user and course enrollment -information, and to enroll a user in a course. +information and to enroll a user in a course. You can use the Enrollment API for web, desktop, and mobile applications. **************************************** -Enrollment API Version 1.0 +Enrollment API Version and Status **************************************** -The Enrollment API is currently at version 1.0. We plan on making +The Enrollment API is currently at version 1.0. We plan to make significant enhancements to this API. ******************************************** -Enrollment API Capabilities +Enrollment API Endpoints ******************************************** -With the Enrollment API, you can complete these tasks. +The Enrollment API supports the following tasks, methods, and endpoints. -* :ref:`Get the user's enrollment status in a course ` +.. list-table:: + :widths: 20 10 70 + :header-rows: 1 -* :ref:`Get enrollment details for a course` + * - Task + - Method + - Endpoint + * - :ref:`Get the user's enrollment status in a course + ` + - GET + - /api/enrollment/v1/enrollment/{user_id},{course_id} + * - :ref:`Get the user's enrollment information for a course + ` + - GET + - /api/enrollment/v1/course/{course_id} + * - :ref:`View a user's enrollments + ` + - GET + - /api/enrollment/v1/enrollment + * - :ref:`Enroll a user in a course + ` + - POST + - /api/enrollment/v1/enrollment{“course_details”:{“course_id”:“*course_id*”}} -* :ref:`View a user's enrollments ` - -* :ref:`Enroll a user in a course ` diff --git a/docs/en_us/platform_api/source/mobile/course_info.rst b/docs/en_us/platform_api/source/mobile/course_info.rst index e301be61a3..47c3fca90e 100644 --- a/docs/en_us/platform_api/source/mobile/course_info.rst +++ b/docs/en_us/platform_api/source/mobile/course_info.rst @@ -1,14 +1,13 @@ ################################################## -Mobile Course Information API +Mobile API Course Information Resource ################################################## -This page describes how to use the Mobile Course Information API -to complete these actions: +With the Mobile API **Course Information** resource, you can complete the +following tasks. -* `Get Course Updates`_ -* `Get Course Handouts`_ +* :ref:`Get updates about a course`. +* :ref:`Get a list of course handouts`. - .. _Get Course Updates: ******************* @@ -50,18 +49,6 @@ Get Course Handouts .. autoclass:: mobile_api.course_info.views.CourseHandoutsList -**Use Case** - -Get the HTML for course handouts. - -**Example request**: - -``GET /api/mobile/v0.5/course_info/{organization}/{course_number}/{course_run}/handouts`` - -**Response Values** - -* handouts_html: The HTML for course handouts. - **Example response** .. code-block:: json diff --git a/docs/en_us/platform_api/source/mobile/endpoints.rst b/docs/en_us/platform_api/source/mobile/endpoints.rst deleted file mode 100644 index 3790949c4f..0000000000 --- a/docs/en_us/platform_api/source/mobile/endpoints.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _edX PlatformMobile API Endpoints: - -################################################ -Mobile API Endpoints -################################################ - -You use the Mobile API enables to view information about users and -their course enrollments, course information, and videos and transcripts. - -The following tasks and endpoints are currently supported. - -.. list-table:: - :widths: 10 70 - :header-rows: 1 - - * - To: - - Use this endpoint: - * - :ref:`Get details about a user` - - /api/mobile/v0.5/users/{username} - * - :ref:`Get course enrollments for about a user` - - /api/mobile/v0.5/users/{username}/course_enrollments/ - * - :ref:`Get or change user status in a course` - - /api/mobile/v0.5/users/{username}/course_status_info/{course_id} - * - :ref:`Get updates for a course` - - /api/mobile/v0.5/course_info/{organization}/{course_number}/{course_run}/updates - * - :ref:`Get handouts for a course` - - /api/mobile/v0.5/course_info/{organization}/{course_number}/{course_run}/handouts - * - :ref:`Get videos in a course` - - /api/mobile/v0.5/video_outlines/courses/{organization}/{course_number}/{course_run} - * - :ref:`Get a video transcript` - - /api/mobile/v0.5/video_outlines/transcripts/{organization}/{course_number}/{course_run}/{video ID}/{language code} diff --git a/docs/en_us/platform_api/source/mobile/index.rst b/docs/en_us/platform_api/source/mobile/index.rst index ff4f8c8767..2d075b0205 100644 --- a/docs/en_us/platform_api/source/mobile/index.rst +++ b/docs/en_us/platform_api/source/mobile/index.rst @@ -8,7 +8,6 @@ Mobile API Version 0.5 :maxdepth: 2 overview - endpoints - users course_info + users video_outlines diff --git a/docs/en_us/platform_api/source/mobile/overview.rst b/docs/en_us/platform_api/source/mobile/overview.rst index 41bf541e47..0d3da876b8 100644 --- a/docs/en_us/platform_api/source/mobile/overview.rst +++ b/docs/en_us/platform_api/source/mobile/overview.rst @@ -4,35 +4,84 @@ Mobile API Overview ################################################ -Use the Mobile API to build mobile applications for students to -view course information and videos for courses on your instance of Open edX. +Use the Mobile API to build mobile applications for students to view course +information and videos for courses on your instance of Open edX. ****************************************** -Mobile API Version 0.5, Alpha +Mobile API Version and Status ****************************************** -The Mobile API is currently at version 0.5 and is an Alpha -release. We plan on making significant enhancements and changes to the API. +The Mobile API is currently at version 0.5 and is an alpha release. We plan on +making significant enhancements and changes to the API. .. caution:: - As this is a new and rapidly evolving API, at this time edX does not guarantee - forward compatibility. We encourage you to use and experiment with the API, - while keeping in mind that endpoints might change. + As this is a new and rapidly evolving API, at this time edX does not + guarantee forward compatibility. We encourage you to use and experiment with + the API, while keeping in mind that endpoints might change. ************************************* -Mobile API Capabilities +Mobile API Resources and Endpoints ************************************* -With the Mobile API, you can complete these tasks. +The Mobile API supports the following resources, tasks, methods, and +endpoints. -* Get :ref:`user details` and :ref:`course enrollments` for a user. +======================== +Mobile API User Resource +======================== -* :ref:`Get or change user status in a course ` +.. list-table:: + :widths: 20 10 70 + :header-rows: 1 -* Get :ref:`updates`, and :ref:`handouts` for courses the user is enrolled in. + * - Task + - Method + - Endpoint + * - :ref:`Get details about a user` + - GET + - /api/mobile/v0.5/users/{username} + * - :ref:`Get course enrollments for a user` + - GET + - /api/mobile/v0.5/users/{username}/course_enrollments/ + * - :ref:`Get a user's status in a course` + - GET + - /api/mobile/v0.5/users/{username}/course_status_info/{course_id} + * - :ref:`Change a user's status in a course` + - PATCH + - /api/mobile/v0.5/rs/{username}/course_status_info/{course_id} -* Get :ref:`videos` and :ref:`transcripts` for courses the user is enrolled in. +======================================== +Mobile API Course Information Resource +======================================== + +.. list-table:: + :widths: 20 10 70 + :header-rows: 1 + + * - Task + - Method + - Endpoint + * - :ref:`Get updates for a course` + - GET + - /api/mobile/v0.5/course_info/{organization}/{course_number}/{course_run}/updates + * - :ref:`Get handouts for a course` + - GET + - /api/mobile/v0.5/course_info/{organization}/{course_number}/{course_run}/handouts + +===================================== +Mobile API Video Outlines Resource +===================================== + +.. list-table:: + :widths: 20 10 70 + :header-rows: 1 + + * - Task + - Method + - Endpoint + * - :ref:`Get videos in a course` + - GET + - /api/mobile/v0.5/video_outlines/courses/{organization}/{course_number}/{course_run} + * - :ref:`Get a video transcript` + - GET + - /api/mobile/v0.5/video_outlines/transcripts/{organization}/{course_number}/{course_run}/{video ID}/{language code} \ No newline at end of file diff --git a/docs/en_us/platform_api/source/mobile/users.rst b/docs/en_us/platform_api/source/mobile/users.rst index 37e27ddc76..c56e3af7db 100644 --- a/docs/en_us/platform_api/source/mobile/users.rst +++ b/docs/en_us/platform_api/source/mobile/users.rst @@ -1,13 +1,13 @@ #################################### -Mobile User API +Mobile API User Resource #################################### -This page describes how to use the Mobile User API to complete -these actions: +With the Mobile API **User** resource, you can complete the following tasks. -* `Get User Details`_ -* `Get a User's Course Enrollments`_ -* `Get or Change User Status in a Course`_ +* :ref:`Get details about a user`. +* :ref:`Get course enrollments for a user`. +* :ref:`Get a user's status in a course`. +* :ref:`Change a user's status in a course`. .. _Get User Details: diff --git a/docs/en_us/platform_api/source/mobile/video_outlines.rst b/docs/en_us/platform_api/source/mobile/video_outlines.rst index 0f77cff0bb..45fb4e7183 100644 --- a/docs/en_us/platform_api/source/mobile/video_outlines.rst +++ b/docs/en_us/platform_api/source/mobile/video_outlines.rst @@ -1,18 +1,18 @@ ################################################## -Mobile Video Outlines API +Mobile API Video Outlines Resource ################################################## -This page describes how to use the Mobile Video Outlines API to -complete these actions: +With the Mobile API **Video Outlines** resource, you can complete the +following tasks. -* `Get the Video List`_ -* `Get a Video Transcript`_ +* :ref:`Get a list of all videos in the course `. +* :ref:`Get a transcript for a specified video and language `. .. _Get the Video List: -******************* -Get the Video List -******************* +************************** +Get the Course Video List +************************** .. autoclass:: mobile_api.video_outlines.views.VideoSummaryList @@ -70,8 +70,4 @@ Get the Video List Get a Video Transcript *********************** -.. autoclass:: mobile_api.video_outlines.views.VideoTranscripts - -**Response Values** - -An HttpResponse with an SRT file download. \ No newline at end of file +.. autoclass:: mobile_api.video_outlines.views.VideoTranscripts \ No newline at end of file diff --git a/docs/en_us/platform_api/source/profile_images/endpoints.rst b/docs/en_us/platform_api/source/profile_images/endpoints.rst deleted file mode 100644 index 6b36655b41..0000000000 --- a/docs/en_us/platform_api/source/profile_images/endpoints.rst +++ /dev/null @@ -1,21 +0,0 @@ -################################################ -Profile Images API Endpoints -################################################ - -You use the Profile Images API to upload or remove profile images. - -If you have staff access, you can remove profile images from any user -account. - -The following tasks and endpoints are currently supported. - -.. list-table:: - :widths: 10 70 - :header-rows: 1 - - * - To: - - Use this endpoint: - * - :ref:`Upload a profile image ` - - POST /api/profile_images/v1/{username}/upload - * - :ref:`Remove profile images ` - - POST /api/profile_images/v1/{username}/remove diff --git a/docs/en_us/platform_api/source/profile_images/index.rst b/docs/en_us/platform_api/source/profile_images/index.rst index 3de6525eee..952538f35e 100644 --- a/docs/en_us/platform_api/source/profile_images/index.rst +++ b/docs/en_us/platform_api/source/profile_images/index.rst @@ -8,5 +8,4 @@ Profile Images API Version 1.0 :maxdepth: 2 overview - endpoints profile_images diff --git a/docs/en_us/platform_api/source/profile_images/overview.rst b/docs/en_us/platform_api/source/profile_images/overview.rst index 78e183e645..f9a5efcc87 100644 --- a/docs/en_us/platform_api/source/profile_images/overview.rst +++ b/docs/en_us/platform_api/source/profile_images/overview.rst @@ -9,16 +9,27 @@ The requesting user can upload or remove his or her own profile image. Users with staff access can remove profile images from any user account. ************************************* -Profile Images API Version 1.0 +Profile Images API Version and Status ************************************* The Profile Images API is currently at version 1.0. ********************************************** -Profile Images API Capabilities +Profile Images API Endpoints ********************************************** -With the Profile Images API, you can complete these tasks. +The Profile Images API supports the following tasks, methods, and endpoints. -* :ref:`Upload profile images ` -* :ref:`Remove profile images ` +.. list-table:: + :widths: 20 10 70 + :header-rows: 1 + + * - Task + - Method + - Endpoint + * - :ref:`Upload a profile image ` + - POST + - /api/profile_images/v1/{username}/upload + * - :ref:`Remove a profile image ` + - POST + - /api/profile_images/v1/{username}/remove \ No newline at end of file diff --git a/docs/en_us/platform_api/source/profile_images/profile_images.rst b/docs/en_us/platform_api/source/profile_images/profile_images.rst index 8866058c88..02365ac0d7 100644 --- a/docs/en_us/platform_api/source/profile_images/profile_images.rst +++ b/docs/en_us/platform_api/source/profile_images/profile_images.rst @@ -1,14 +1,14 @@ .. Profile Images API: ################################################## -Profile Images API +Profile Images API Profile Images Resource ################################################## -This page contains information on using the Profile Images API to complete -the following actions. +With the Profile Images API **Profile Images** resource, you can complete the +following tasks. -* `Upload a Profile Image`_ -* `Remove Profile Images`_ +* :ref:`Upload a profile image `. +* :ref:`Remove profile images `. .. _Upload a Profile Image: @@ -18,7 +18,7 @@ Upload a Profile Image .. autoclass:: profile_images.views.ProfileImageUploadView -**Example response** +**Example Response** .. code-block:: json @@ -26,15 +26,15 @@ Upload a Profile Image No Content -.. _Remove Profile Images: +.. _Remove a Profile Image: ************************************************** -Remove Profile Images +Remove a Profile Image ************************************************** .. autoclass:: profile_images.views.ProfileImageRemoveView -**Example response** +**Example Response** .. code-block:: json diff --git a/docs/en_us/platform_api/source/user/accounts.rst b/docs/en_us/platform_api/source/user/accounts.rst index 1790ebab18..ec02f93ca0 100644 --- a/docs/en_us/platform_api/source/user/accounts.rst +++ b/docs/en_us/platform_api/source/user/accounts.rst @@ -1,11 +1,11 @@ .. _User Accounts API: ################################################## -User Accounts API +User API User Accounts Resource ################################################## -This page contains information on using the User Accounts API to -complete the following actions. +With the User API **User Accounts** resource, you can complete the following +tasks. * `Get and Update the User's Account Information`_ @@ -15,129 +15,7 @@ complete the following actions. Get and Update the User's Account Information ********************************************** -.. .. autoclass:: user_api.accounts.views.AccountView - -**Use Cases** - -Get or update a user's account information. Updates are supported only through -merge patch. - -**Example Requests**: - -GET /api/user/v1/accounts/{username}/[?view=shared] - -PATCH /api/user/v1/accounts/{username}/{"key":"value"} "application/merge-patch+json" - -**Response Values for GET** - -If the user makes the request for her own account, or makes a request for -another account and has "is_staff" access, the response contains: - -* username: The username associated with the account. - -* name: The full name of the user. - -* email: email for the user (the new email address must be confirmed via a - confirmation email, so GET will not reflect the change until the address has - been confirmed). - -* date_joined: The date the account was created, in the string format provided - by datetime. For example, "2014-08-26T17:52:11Z". - -* gender: One of the following values: - * "m" - * "f" - * "o" - * null - -* year_of_birth: The year the user was born, as an integer, or null. - -* level_of_education: One of the following values: - - * "p": PhD or Doctorate - * "m": Master's or professional degree - * "b": Bachelor's degree - * "a": Associate's degree - * "hs": Secondary/high school - * "jhs": Junior secondary/junior high/middle school - * "el": Elementary/primary school - * "none": None - * "o": Other - * null: The user did not enter a value. - -* language: The user's preferred language, or null. - -* country: null (not set), or a Country corresponding to one of the ISO 3166-1 - countries. - -* country: A ISO 3166 country code or null. - -* mailing_address: The textual representation of the user's mailing address, or - null. - -* goals: The textual representation of the user's goals, or null. - -* bio: null or textural representation of user biographical information ("about - me"). - -* is_active: boolean representation of whether a user is active. - -* profile_image: JSON representation of a user's profile image information. The - keys are: the user's profile image: - -* "has_image": boolean indicating whether the user has a profile image. - -* "image_url_*": absolute URL to various sizes of a user's profile image, where - '*' matches a representation of the corresponding image size such as 'small', - 'medium', 'large', and 'full'. These are configurable via - PROFILE_IMAGE_SIZES_MAP. - -* requires_parental_consent: true if the user is a minor requiring parental - consent. - -* language_proficiencies: array of language preferences. Each preference is a - JSON object with the following keys: - -* "code": string ISO 639-1 language code e.g. "en". - -For all text fields, clients rendering the values should take care to HTML -escape them to avoid script injections, as the data is stored -exactly as specified. The intention is that plain text is -supported, not HTML. - -If a user who does not have "is_staff" access requests account information for -a different user, only a subset of these fields is returned. The fields -returned depend on the configuration setting ACCOUNT_VISIBILITY_CONFIGURATION, -and the visibility preference of the user for whom data is requested. - -Note that a user can view which account fields they have shared with other -users by requesting their own username and providing the url parameter -"view=shared". - -If no user exists with the specified username, a 404 error is returned. - -**Response Values for PATCH** - -Users can only modify their own account information. If the requesting user -does not have username "username", this method will return with a status of 403 -for staff access but a 404 for ordinary users to avoid leaking the existence of -the account. - -If no user exists with the specified username, a 404 error is returned. - -If "application/merge-patch+json" is not the specified content type, a 415 -error is returned. - -If the update could not be completed due to validation errors, this method -returns a 400 error with all error messages in the "field_errors" field of the -returned JSON. - -If the update could not be completed due to a failure at the time of the -update, a 400 error is returned with specific errors in the returned JSON -collection. - -If the update is successful, a 204 status is returned with no additional -content. +.. autoclass:: user_api.accounts.views.AccountView **Example response showing the user's account information** @@ -153,11 +31,11 @@ content. "name": "John Doe", "language": "", "gender": "m", - "year_of_birth": 2007, + "year_of_birth": 1987, "level_of_education": "m", "goals": "Professional Development", "country": US, - "mailing_address": "406 Highland Ave., Somerville, MA 02144", + "mailing_address": "123 Main Street, Anytown, MA 02144", "email": "johndoe@company.com", "date_joined": "2015-03-18T13:42:40Z" } diff --git a/docs/en_us/platform_api/source/user/endpoints.rst b/docs/en_us/platform_api/source/user/endpoints.rst deleted file mode 100644 index 254766327f..0000000000 --- a/docs/en_us/platform_api/source/user/endpoints.rst +++ /dev/null @@ -1,36 +0,0 @@ -################################################ -User API Endpoints -################################################ - -You use the User API to view information about users and update -your own account. - -The following tasks and endpoints are currently supported. - -.. list-table:: - :widths: 10 70 - :header-rows: 1 - - * - To: - - Use this endpoint: - * - :ref:`Get a user's account information ` - - GET /api/user/v1/accounts/{username}/[?view=shared] - * - :ref:`Update your account information ` - - PATCH /api/user/v1/accounts/{username}/{“key”:”value”} - * - :ref:`Get a user's preferences information ` - - GET /api/user/v1/preferences/{username}/ - * - :ref:`Update a user's preferences information ` - - PATCH /api/user/v1/preferences/{username}/ - * - :ref:`Get a specific preference ` - - GET /api/user/v1/preferences/{username}/{preference_key} - * - :ref:`Update a specific preference ` - - PUT /api/user/v1/preferences/{username}/{preference_key} - * - :ref:`Delete a specific preference ` - - DELETE /api/user/v1/preferences/{username}/{preference_key} diff --git a/docs/en_us/platform_api/source/user/index.rst b/docs/en_us/platform_api/source/user/index.rst index 97a1bb529a..575de30441 100644 --- a/docs/en_us/platform_api/source/user/index.rst +++ b/docs/en_us/platform_api/source/user/index.rst @@ -8,6 +8,5 @@ User API Version 1.0 :maxdepth: 2 overview - endpoints accounts preferences diff --git a/docs/en_us/platform_api/source/user/overview.rst b/docs/en_us/platform_api/source/user/overview.rst index dbda4f7dbb..7dc96ca262 100644 --- a/docs/en_us/platform_api/source/user/overview.rst +++ b/docs/en_us/platform_api/source/user/overview.rst @@ -7,21 +7,67 @@ Use the User API to view and update account and preference information. You can use the User API for web, desktop, and mobile applications. ************************************* -User API Version 1.0 +User API Version and Status ************************************* The User API is currently at version 1.0. We plan on making significant enhancements to this API. ********************************************** -User API Capabilities +User API Resources and Endpoints ********************************************** -With the User API, you can complete these tasks. +The User API supports the following resources, tasks, methods, and endpoints. -* :ref:`Get and update the users' account information ` -* :ref:`Get and update the user's preferences information ` -* :ref:`Get, update or delete a specific preference: ` +============================= +User Accounts API Resource +============================= + +.. list-table:: + :widths: 20 10 70 + :header-rows: 1 + + * - Task + - Method + - Endpoint + * - :ref:`Get a user's account information ` + - GET + - /api/user/v1/accounts/{username}/[?view=shared] + * - :ref:`Update your account information ` + - PATCH + - /api/user/v1/accounts/{username}/{“key”:”value”} + + +============================= +User Preferences API Resource +============================= + +.. list-table:: + :widths: 20 10 70 + :header-rows: 1 + + * - Task + - Method + - Endpoint + * - :ref:`Get a user's preferences information + ` + - GET + - /api/user/v1/preferences/{username}/ + * - :ref:`Update a user's preferences information + ` + - PATCH + - /api/user/v1/preferences/{username}/ + * - :ref:`Get a specific preference + ` + - GET + - /api/user/v1/preferences/{username}/{preference_key} + * - :ref:`Update a specific preference + ` + - PUT + - /api/user/v1/preferences/{username}/{preference_key} + * - :ref:`Delete a specific preference + ` + - DELETE + - /api/user/v1/preferences/{username}/{preference_key} diff --git a/docs/en_us/platform_api/source/user/preferences.rst b/docs/en_us/platform_api/source/user/preferences.rst index 58725324eb..c786c8b9ed 100644 --- a/docs/en_us/platform_api/source/user/preferences.rst +++ b/docs/en_us/platform_api/source/user/preferences.rst @@ -1,11 +1,11 @@ .. _User Preferences API: ################################################## -User Preferences API +User API User Preferences Resource ################################################## -This page contains information on using the User Preferences API to -complete the following actions. +With the User API **User Preferences** resource, you can complete the +following tasks. * `Get and Update the User's Preferences Information`_ * `Get, Update, or Delete a Specific Preference`_ diff --git a/lms/djangoapps/branding/tests/test_page.py b/lms/djangoapps/branding/tests/test_page.py index ac4357e4f0..4b3c725a8c 100644 --- a/lms/djangoapps/branding/tests/test_page.py +++ b/lms/djangoapps/branding/tests/test_page.py @@ -220,7 +220,7 @@ class IndexPageCourseCardsSortingTests(ModuleStoreTestCase): self.assertNotIn('
+
+
+
+
+

We couldn't find the team "blah".

+
+
+
+
-
1-10 of 24 topics | diff --git a/lms/templates/ux/reference/teams-create.html b/lms/templates/ux/reference/teams-create.html index 811f467455..3fae1bce56 100644 --- a/lms/templates/ux/reference/teams-create.html +++ b/lms/templates/ux/reference/teams-create.html @@ -139,7 +139,16 @@ Create New Team | [Course name]

If you cannot find an existing team to join or would like to team up with a group of friends, create a new team.

- +
+
+
+

Oops!

+
+

We couldn't create your team because something needs to be fixed below.

+
+
+
+
diff --git a/lms/templates/verify_student/incourse_reverify.html b/lms/templates/verify_student/incourse_reverify.html index a7b101dff4..3c7be5e68a 100644 --- a/lms/templates/verify_student/incourse_reverify.html +++ b/lms/templates/verify_student/incourse_reverify.html @@ -18,9 +18,7 @@ from django.utils.translation import ugettext as _ % endfor <%block name="js_extra"> - - <%static:js group='incourse_reverify'/> diff --git a/lms/templates/verify_student/missed_deadline.html b/lms/templates/verify_student/missed_deadline.html new file mode 100644 index 0000000000..26192f2fd5 --- /dev/null +++ b/lms/templates/verify_student/missed_deadline.html @@ -0,0 +1,29 @@ +<%! +from django.utils.translation import ugettext as _ +from verify_student.views import PayAndVerifyView +%> +<%namespace name='static' file='../static_content.html'/> + +<%inherit file="../main.html" /> + +<%block name="pagetitle"> + % if deadline_name == PayAndVerifyView.VERIFICATION_DEADLINE: + ${_("Verification Deadline Has Passed")} + % elif deadline_name == PayAndVerifyView.UPGRADE_DEADLINE: + ${_("Upgrade Deadline Has Passed")} + % endif + + +<%block name="content"> +
+

+ + % if deadline_name == PayAndVerifyView.VERIFICATION_DEADLINE: + ${_(u"The verification deadline for {course_name} was {date}. Verification is no longer available.").format( + course_name=course.display_name, date=deadline)} + % elif deadline_name == PayAndVerifyView.UPGRADE_DEADLINE: + ${_(u"The deadline to upgrade to a verified certificate for this course has passed. You can still earn an honor code certificate.")} + % endif +

+
+ diff --git a/lms/templates/verify_student/missed_verification_deadline.html b/lms/templates/verify_student/missed_verification_deadline.html deleted file mode 100644 index 5c69a3052d..0000000000 --- a/lms/templates/verify_student/missed_verification_deadline.html +++ /dev/null @@ -1,18 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> -<%namespace name='static' file='../static_content.html'/> - -<%inherit file="../main.html" /> - -<%block name="pagetitle">${_("Verification Deadline Has Passed")} - -<%block name="content"> -
-

${_( - u"The verification deadline for {course_name} was {date}. " - u"Verification is no longer available." - ).format( - course_name=course.display_name, - date=deadline - )}

-
- diff --git a/lms/templates/verify_student/pay_and_verify.html b/lms/templates/verify_student/pay_and_verify.html index 7b90d72001..9c02e5f40a 100644 --- a/lms/templates/verify_student/pay_and_verify.html +++ b/lms/templates/verify_student/pay_and_verify.html @@ -35,9 +35,7 @@ from verify_student.views import PayAndVerifyView % endfor <%block name="js_extra"> - - <%static:js group='verify_student'/> diff --git a/lms/templates/verify_student/reverify.html b/lms/templates/verify_student/reverify.html index 8218392e95..d3e6340115 100644 --- a/lms/templates/verify_student/reverify.html +++ b/lms/templates/verify_student/reverify.html @@ -16,9 +16,7 @@ from django.utils.translation import ugettext as _ % endfor <%block name="js_extra"> - - <%static:js group='reverify'/> diff --git a/lms/tests.py b/lms/tests.py index 09946a9fbb..cf9a082b8b 100644 --- a/lms/tests.py +++ b/lms/tests.py @@ -10,7 +10,6 @@ from edxmako import add_lookup, LOOKUP from lms import startup from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -from util import keyword_substitution class LmsModuleTests(TestCase): diff --git a/lms/urls.py b/lms/urls.py index 70d1bf4619..72ffb245dd 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -137,7 +137,7 @@ js_info_dict = { urlpatterns += ( # Serve catalog of localized strings to be rendered by Javascript - url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), + url(r'^i18n.js$', 'django.views.i18n.javascript_catalog', js_info_dict), ) # sysadmin dashboard, to see what courses are loaded, to delete & load courses @@ -605,7 +605,6 @@ if settings.FEATURES.get('RUN_AS_ANALYTICS_SERVER_ENABLED'): urlpatterns += ( url(r'^edinsights_service/', include('edinsights.core.urls')), ) - import edinsights.core.registry # FoldIt views urlpatterns += ( diff --git a/openedx/core/djangoapps/content/course_overviews/migrations/0005_add_enrollment_fields.py b/openedx/core/djangoapps/content/course_overviews/migrations/0005_add_enrollment_fields.py new file mode 100644 index 0000000000..25c94e240a --- /dev/null +++ b/openedx/core/djangoapps/content/course_overviews/migrations/0005_add_enrollment_fields.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +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): + # The default values for these new columns may not match the actual + # values of courses already present in the table. To ensure that the + # cached values are correct, we must clear the table before adding any + # new columns. + db.clear_table('course_overviews_courseoverview') + + # Adding field 'CourseOverview.enrollment_start' + db.add_column('course_overviews_courseoverview', 'enrollment_start', + self.gf('django.db.models.fields.DateTimeField')(null=True), + keep_default=False) + + # Adding field 'CourseOverview.enrollment_end' + db.add_column('course_overviews_courseoverview', 'enrollment_end', + self.gf('django.db.models.fields.DateTimeField')(null=True), + keep_default=False) + + # Adding field 'CourseOverview.enrollment_domain' + db.add_column('course_overviews_courseoverview', 'enrollment_domain', + self.gf('django.db.models.fields.TextField')(null=True), + keep_default=False) + + # Adding field 'CourseOverview.invitation_only' + db.add_column('course_overviews_courseoverview', 'invitation_only', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'CourseOverview.max_student_enrollments_allowed' + db.add_column('course_overviews_courseoverview', 'max_student_enrollments_allowed', + self.gf('django.db.models.fields.IntegerField')(null=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'CourseOverview.enrollment_start' + db.delete_column('course_overviews_courseoverview', 'enrollment_start') + + # Deleting field 'CourseOverview.enrollment_end' + db.delete_column('course_overviews_courseoverview', 'enrollment_end') + + # Deleting field 'CourseOverview.enrollment_domain' + db.delete_column('course_overviews_courseoverview', 'enrollment_domain') + + # Deleting field 'CourseOverview.invitation_only' + db.delete_column('course_overviews_courseoverview', 'invitation_only') + + # Deleting field 'CourseOverview.max_student_enrollments_allowed' + db.delete_column('course_overviews_courseoverview', 'max_student_enrollments_allowed') + + + models = { + 'course_overviews.courseoverview': { + 'Meta': {'object_name': 'CourseOverview'}, + '_location': ('xmodule_django.models.UsageKeyField', [], {'max_length': '255'}), + '_pre_requisite_courses_json': ('django.db.models.fields.TextField', [], {}), + 'advertised_start': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'cert_html_view_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'cert_name_long': ('django.db.models.fields.TextField', [], {}), + 'cert_name_short': ('django.db.models.fields.TextField', [], {}), + 'certificates_display_behavior': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'certificates_show_before_end': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'course_image_url': ('django.db.models.fields.TextField', [], {}), + 'days_early_for_beta': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'display_name': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'display_number_with_default': ('django.db.models.fields.TextField', [], {}), + 'display_org_with_default': ('django.db.models.fields.TextField', [], {}), + 'end': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'end_of_course_survey_url': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'enrollment_domain': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'enrollment_end': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'enrollment_start': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'facebook_url': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'has_any_active_web_certificate': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'primary_key': 'True', 'db_index': 'True'}), + 'invitation_only': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'lowest_passing_grade': ('django.db.models.fields.DecimalField', [], {'max_digits': '5', 'decimal_places': '2', 'null': 'True'}), + 'max_student_enrollments_allowed': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'mobile_available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'social_sharing_url': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'start': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'visible_to_staff_only': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + } + } + + complete_apps = ['course_overviews'] \ No newline at end of file diff --git a/openedx/core/djangoapps/content/course_overviews/models.py b/openedx/core/djangoapps/content/course_overviews/models.py index 4b8429f9cc..517eda28a5 100644 --- a/openedx/core/djangoapps/content/course_overviews/models.py +++ b/openedx/core/djangoapps/content/course_overviews/models.py @@ -5,7 +5,7 @@ Declaration of CourseOverview model import json import django.db.models -from django.db.models.fields import BooleanField, DateTimeField, DecimalField, TextField, FloatField +from django.db.models.fields import BooleanField, DateTimeField, DecimalField, TextField, FloatField, IntegerField from django.utils.translation import ugettext from util.date_utils import strftime_localized @@ -60,6 +60,13 @@ class CourseOverview(django.db.models.Model): visible_to_staff_only = BooleanField() _pre_requisite_courses_json = TextField() # JSON representation of list of CourseKey strings + # Enrollment details + enrollment_start = DateTimeField(null=True) + enrollment_end = DateTimeField(null=True) + enrollment_domain = TextField(null=True) + invitation_only = BooleanField(default=False) + max_student_enrollments_allowed = IntegerField(null=True) + @staticmethod def _create_from_course(course): """ @@ -114,7 +121,13 @@ class CourseOverview(django.db.models.Model): days_early_for_beta=course.days_early_for_beta, mobile_available=course.mobile_available, visible_to_staff_only=course.visible_to_staff_only, - _pre_requisite_courses_json=json.dumps(course.pre_requisite_courses) + _pre_requisite_courses_json=json.dumps(course.pre_requisite_courses), + + enrollment_start=course.enrollment_start, + enrollment_end=course.enrollment_end, + enrollment_domain=course.enrollment_domain, + invitation_only=course.invitation_only, + max_student_enrollments_allowed=course.max_student_enrollments_allowed, ) @staticmethod diff --git a/openedx/core/djangoapps/content/course_overviews/signals.py b/openedx/core/djangoapps/content/course_overviews/signals.py index 37bfcd2681..c2141847b1 100644 --- a/openedx/core/djangoapps/content/course_overviews/signals.py +++ b/openedx/core/djangoapps/content/course_overviews/signals.py @@ -3,9 +3,8 @@ Signal handler for invalidating cached course overviews """ from django.dispatch.dispatcher import receiver -from xmodule.modulestore.django import SignalHandler - from .models import CourseOverview +from xmodule.modulestore.django import SignalHandler @receiver(SignalHandler.course_published) @@ -15,3 +14,12 @@ def _listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable invalidates the corresponding CourseOverview cache entry if one exists. """ CourseOverview.objects.filter(id=course_key).delete() + + +@receiver(SignalHandler.course_deleted) +def _listen_for_course_delete(sender, course_key, **kwargs): # pylint: disable=unused-argument + """ + Catches the signal that a course has been deleted from Studio and + invalidates the corresponding CourseOverview cache entry if one exists. + """ + CourseOverview.objects.filter(id=course_key).delete() diff --git a/openedx/core/djangoapps/content/course_overviews/tests.py b/openedx/core/djangoapps/content/course_overviews/tests.py index 8a56bb5172..25035b2606 100644 --- a/openedx/core/djangoapps/content/course_overviews/tests.py +++ b/openedx/core/djangoapps/content/course_overviews/tests.py @@ -91,6 +91,9 @@ class CourseOverviewTestCase(ModuleStoreTestCase): 'display_name_with_default', 'start_date_is_still_default', 'pre_requisite_courses', + 'enrollment_domain', + 'invitation_only', + 'max_student_enrollments_allowed', ] for attribute_name in fields_to_test: course_value = getattr(course, attribute_name) @@ -125,24 +128,38 @@ class CourseOverviewTestCase(ModuleStoreTestCase): # resulting values are often off by fractions of a second. So, as a # workaround, we simply test if the start and end times are the same # number of seconds from the Unix epoch. - others_to_test = [( - course_image_url(course), - course_overview_cache_miss.course_image_url, - course_overview_cache_hit.course_image_url - ), ( - get_active_web_certificate(course) is not None, - course_overview_cache_miss.has_any_active_web_certificate, - course_overview_cache_hit.has_any_active_web_certificate - - ), ( - get_seconds_since_epoch(course.start), - get_seconds_since_epoch(course_overview_cache_miss.start), - get_seconds_since_epoch(course_overview_cache_hit.start), - ), ( - get_seconds_since_epoch(course.end), - get_seconds_since_epoch(course_overview_cache_miss.end), - get_seconds_since_epoch(course_overview_cache_hit.end), - )] + others_to_test = [ + ( + course_image_url(course), + course_overview_cache_miss.course_image_url, + course_overview_cache_hit.course_image_url + ), + ( + get_active_web_certificate(course) is not None, + course_overview_cache_miss.has_any_active_web_certificate, + course_overview_cache_hit.has_any_active_web_certificate + ), + ( + get_seconds_since_epoch(course.start), + get_seconds_since_epoch(course_overview_cache_miss.start), + get_seconds_since_epoch(course_overview_cache_hit.start), + ), + ( + get_seconds_since_epoch(course.end), + get_seconds_since_epoch(course_overview_cache_miss.end), + get_seconds_since_epoch(course_overview_cache_hit.end), + ), + ( + get_seconds_since_epoch(course.enrollment_start), + get_seconds_since_epoch(course_overview_cache_miss.enrollment_start), + get_seconds_since_epoch(course_overview_cache_hit.enrollment_start), + ), + ( + get_seconds_since_epoch(course.enrollment_end), + get_seconds_since_epoch(course_overview_cache_miss.enrollment_end), + get_seconds_since_epoch(course_overview_cache_hit.enrollment_end), + ), + ] for (course_value, cache_miss_value, cache_hit_value) in others_to_test: self.assertEqual(course_value, cache_miss_value) self.assertEqual(cache_miss_value, cache_hit_value) @@ -211,7 +228,7 @@ class CourseOverviewTestCase(ModuleStoreTestCase): @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) def test_course_overview_cache_invalidation(self, modulestore_type): """ - Tests that when a course is published, the corresponding + Tests that when a course is published or deleted, the corresponding course_overview is removed from the cache. Arguments: @@ -236,6 +253,11 @@ class CourseOverviewTestCase(ModuleStoreTestCase): course_overview_2 = CourseOverview.get_from_id(course.id) self.assertFalse(course_overview_2.mobile_available) + # Verify that when the course is deleted, the corresponding CourseOverview is deleted as well. + with self.assertRaises(CourseOverview.DoesNotExist): + self.store.delete_course(course.id, ModuleStoreEnum.UserID.test) + CourseOverview.get_from_id(course.id) + @ddt.data((ModuleStoreEnum.Type.mongo, 1, 1), (ModuleStoreEnum.Type.split, 3, 4)) @ddt.unpack def test_course_overview_caching(self, modulestore_type, min_mongo_calls, max_mongo_calls): diff --git a/openedx/core/djangoapps/content/course_structures/migrations/0002_auto__add_field_coursestructure_discussion_id_map_json.py b/openedx/core/djangoapps/content/course_structures/migrations/0002_auto__add_field_coursestructure_discussion_id_map_json.py new file mode 100644 index 0000000000..5d8cb4bb41 --- /dev/null +++ b/openedx/core/djangoapps/content/course_structures/migrations/0002_auto__add_field_coursestructure_discussion_id_map_json.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +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 field 'CourseStructure.discussion_id_map_json' + db.add_column('course_structures_coursestructure', 'discussion_id_map_json', + self.gf('django.db.models.fields.TextField')(null=True, blank=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'CourseStructure.discussion_id_map_json' + db.delete_column('course_structures_coursestructure', 'discussion_id_map_json') + + + models = { + 'course_structures.coursestructure': { + 'Meta': {'object_name': 'CourseStructure'}, + 'course_id': ('xmodule_django.models.CourseKeyField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'discussion_id_map_json': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'structure_json': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['course_structures'] \ No newline at end of file diff --git a/openedx/core/djangoapps/content/course_structures/models.py b/openedx/core/djangoapps/content/course_structures/models.py index 82acf61173..b28e416bb2 100644 --- a/openedx/core/djangoapps/content/course_structures/models.py +++ b/openedx/core/djangoapps/content/course_structures/models.py @@ -5,7 +5,7 @@ from collections import OrderedDict from model_utils.models import TimeStampedModel from util.models import CompressedTextField -from xmodule_django.models import CourseKeyField +from xmodule_django.models import CourseKeyField, UsageKey logger = logging.getLogger(__name__) # pylint: disable=invalid-name @@ -21,6 +21,9 @@ class CourseStructure(TimeStampedModel): # we'd have to be careful about caching. structure_json = CompressedTextField(verbose_name='Structure JSON', blank=True, null=True) + # JSON mapping of discussion ids to usage keys for the corresponding discussion modules + discussion_id_map_json = CompressedTextField(verbose_name='Discussion ID Map JSON', blank=True, null=True) + @property def structure(self): if self.structure_json: @@ -37,6 +40,19 @@ class CourseStructure(TimeStampedModel): self._traverse_tree(self.structure['root'], self.structure['blocks'], ordered_blocks) return ordered_blocks + @property + def discussion_id_map(self): + """ + Return a mapping of discussion ids to usage keys of the corresponding discussion modules. + """ + if self.discussion_id_map_json: + result = json.loads(self.discussion_id_map_json) + for discussion_id in result: + # Usage key strings might not include the course run, so we add it back in with map_into_course + result[discussion_id] = UsageKey.from_string(result[discussion_id]).map_into_course(self.course_id) + return result + return None + def _traverse_tree(self, block, unordered_structure, ordered_blocks, parent=None): """ Traverses the tree and fills in the ordered_blocks OrderedDict with the blocks in diff --git a/openedx/core/djangoapps/content/course_structures/signals.py b/openedx/core/djangoapps/content/course_structures/signals.py index 4070c5787e..18ebe3544c 100644 --- a/openedx/core/djangoapps/content/course_structures/signals.py +++ b/openedx/core/djangoapps/content/course_structures/signals.py @@ -2,12 +2,22 @@ from django.dispatch.dispatcher import receiver from xmodule.modulestore.django import SignalHandler +from .models import CourseStructure + @receiver(SignalHandler.course_published) def listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable=unused-argument # Import tasks here to avoid a circular import. from .tasks import update_course_structure + # Delete the existing discussion id map cache to avoid inconsistencies + try: + structure = CourseStructure.objects.get(course_id=course_key) + structure.discussion_id_map_json = None + structure.save() + except CourseStructure.DoesNotExist: + pass + # Note: The countdown=0 kwarg is set to to ensure the method below does not attempt to access the course # before the signal emitter has finished all operations. This is also necessary to ensure all tests pass. update_course_structure.apply_async([unicode(course_key)], countdown=0) diff --git a/openedx/core/djangoapps/content/course_structures/tasks.py b/openedx/core/djangoapps/content/course_structures/tasks.py index 5ed989be33..d246adf17d 100644 --- a/openedx/core/djangoapps/content/course_structures/tasks.py +++ b/openedx/core/djangoapps/content/course_structures/tasks.py @@ -17,6 +17,7 @@ def _generate_course_structure(course_key): course = modulestore().get_course(course_key, depth=None) blocks_stack = [course] blocks_dict = {} + discussions = {} while blocks_stack: curr_block = blocks_stack.pop() children = curr_block.get_children() if curr_block.has_children else [] @@ -28,6 +29,11 @@ def _generate_course_structure(course_key): "children": [unicode(child.scope_ids.usage_id) for child in children] } + if (curr_block.category == 'discussion' and + hasattr(curr_block, 'discussion_id') and + curr_block.discussion_id): + discussions[curr_block.discussion_id] = unicode(curr_block.scope_ids.usage_id) + # Retrieve these attributes separately so that we can fail gracefully # if the block doesn't have the attribute. attrs = (('graded', False), ('format', None)) @@ -43,8 +49,11 @@ def _generate_course_structure(course_key): # Add this blocks children to the stack so that we can traverse them as well. blocks_stack.extend(children) return { - "root": unicode(course.scope_ids.usage_id), - "blocks": blocks_dict + 'structure': { + "root": unicode(course.scope_ids.usage_id), + "blocks": blocks_dict + }, + 'discussion_id_map': discussions } @@ -69,13 +78,18 @@ def update_course_structure(course_key): log.exception('An error occurred while generating course structure: %s', ex.message) raise - structure_json = json.dumps(structure) + structure_json = json.dumps(structure['structure']) + discussion_id_map_json = json.dumps(structure['discussion_id_map']) - cs, created = CourseStructure.objects.get_or_create( + structure_model, created = CourseStructure.objects.get_or_create( course_id=course_key, - defaults={'structure_json': structure_json} + defaults={ + 'structure_json': structure_json, + 'discussion_id_map_json': discussion_id_map_json + } ) if not created: - cs.structure_json = structure_json - cs.save() + structure_model.structure_json = structure_json + structure_model.discussion_id_map_json = discussion_id_map_json + structure_model.save() diff --git a/openedx/core/djangoapps/content/course_structures/tests.py b/openedx/core/djangoapps/content/course_structures/tests.py index c2f1b4f5cf..38e0237270 100644 --- a/openedx/core/djangoapps/content/course_structures/tests.py +++ b/openedx/core/djangoapps/content/course_structures/tests.py @@ -1,5 +1,6 @@ import json +from xmodule_django.models import UsageKey from xmodule.modulestore.django import SignalHandler from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory @@ -21,8 +22,18 @@ class SignalDisconnectTestMixin(object): class CourseStructureTaskTests(ModuleStoreTestCase): def setUp(self, **kwargs): super(CourseStructureTaskTests, self).setUp() - self.course = CourseFactory.create() + self.course = CourseFactory.create(org='TestX', course='TS101', run='T1') self.section = ItemFactory.create(parent=self.course, category='chapter', display_name='Test Section') + self.discussion_module_1 = ItemFactory.create( + parent=self.course, + category='discussion', + discussion_id='test_discussion_id_1' + ) + self.discussion_module_2 = ItemFactory.create( + parent=self.course, + category='discussion', + discussion_id='test_discussion_id_2' + ) CourseStructure.objects.all().delete() def test_generate_course_structure(self): @@ -52,7 +63,7 @@ class CourseStructureTaskTests(ModuleStoreTestCase): self.maxDiff = None actual = _generate_course_structure(self.course.id) - self.assertDictEqual(actual, expected) + self.assertDictEqual(actual['structure'], expected) def test_structure_json(self): """ @@ -138,7 +149,7 @@ class CourseStructureTaskTests(ModuleStoreTestCase): structure = _generate_course_structure(self.course.id) usage_key = unicode(module.location) - actual = structure['blocks'][usage_key] + actual = structure['structure']['blocks'][usage_key] expected = { "usage_key": usage_key, "block_type": category, @@ -149,6 +160,53 @@ class CourseStructureTaskTests(ModuleStoreTestCase): } self.assertEqual(actual, expected) + def test_generate_discussion_id_map(self): + id_map = {} + + def add_block(block): + """Adds the given block and all of its children to the expected discussion id map""" + children = block.get_children() if block.has_children else [] + + if block.category == 'discussion': + id_map[block.discussion_id] = unicode(block.location) + + for child in children: + add_block(child) + + add_block(self.course) + + actual = _generate_course_structure(self.course.id) + self.assertEqual(actual['discussion_id_map'], id_map) + + def test_discussion_id_map_json(self): + id_map = { + 'discussion_id_1': 'module_location_1', + 'discussion_id_2': 'module_location_2' + } + id_map_json = json.dumps(id_map) + structure = CourseStructure.objects.create(course_id=self.course.id, discussion_id_map_json=id_map_json) + self.assertEqual(structure.discussion_id_map_json, id_map_json) + + structure = CourseStructure.objects.get(course_id=self.course.id) + self.assertEqual(structure.discussion_id_map_json, id_map_json) + + def test_discussion_id_map(self): + id_map = { + 'discussion_id_1': 'block-v1:TestX+TS101+T1+type@discussion+block@b141953dff414921a715da37eb14ecdc', + 'discussion_id_2': 'i4x://TestX/TS101/discussion/466f474fa4d045a8b7bde1b911e095ca' + } + id_map_json = json.dumps(id_map) + structure = CourseStructure.objects.create(course_id=self.course.id, discussion_id_map_json=id_map_json) + expected_id_map = { + key: UsageKey.from_string(value).map_into_course(self.course.id) + for key, value in id_map.iteritems() + } + self.assertEqual(structure.discussion_id_map, expected_id_map) + + def test_discussion_id_map_missing(self): + structure = CourseStructure.objects.create(course_id=self.course.id) + self.assertIsNone(structure.discussion_id_map) + def test_update_course_structure(self): """ Test the actual task that orchestrates data generation and updating the database. @@ -158,8 +216,13 @@ class CourseStructureTaskTests(ModuleStoreTestCase): self.assertRaises(ValueError, update_course_structure, course_id) # Ensure a CourseStructure object is created - structure = _generate_course_structure(course_id) + expected_structure = _generate_course_structure(course_id) update_course_structure(unicode(course_id)) - cs = CourseStructure.objects.get(course_id=course_id) - self.assertEqual(cs.course_id, course_id) - self.assertEqual(cs.structure, structure) + structure = CourseStructure.objects.get(course_id=course_id) + self.assertEqual(structure.course_id, course_id) + self.assertEqual(structure.structure, expected_structure['structure']) + self.assertEqual(structure.discussion_id_map.keys(), expected_structure['discussion_id_map'].keys()) + self.assertEqual( + [unicode(value) for value in structure.discussion_id_map.values()], + expected_structure['discussion_id_map'].values() + ) diff --git a/openedx/core/djangoapps/course_groups/models.py b/openedx/core/djangoapps/course_groups/models.py index 3fc6828bdc..ff80d96979 100644 --- a/openedx/core/djangoapps/course_groups/models.py +++ b/openedx/core/djangoapps/course_groups/models.py @@ -18,7 +18,7 @@ class CourseUserGroup(models.Model): which may be treated specially. For example, a user can be in at most one cohort per course, and cohorts are used to split up the forums by group. """ - class Meta: + class Meta(object): # pylint: disable=missing-docstring unique_together = (('name', 'course_id'), ) name = models.CharField(max_length=255, diff --git a/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py b/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py index 57bb63b26e..3faaa0de2f 100644 --- a/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py +++ b/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py @@ -6,7 +6,6 @@ Test the partitions and partitions service import json from django.conf import settings import django.test -from django.test.utils import override_settings from mock import patch from unittest import skipUnless @@ -14,8 +13,8 @@ from courseware.masquerade import handle_ajax, setup_masquerade from courseware.tests.test_masquerade import StaffMasqueradeTestCase from student.tests.factories import UserFactory from xmodule.partitions.partitions import Group, UserPartition, UserPartitionError -from xmodule.modulestore.django import modulestore, clear_existing_modulestores -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, mixed_store_config, TEST_DATA_MIXED_TOY_MODULESTORE +from xmodule.modulestore.django import modulestore +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_TOY_MODULESTORE from opaque_keys.edx.locations import SlashSeparatedCourseKey from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme diff --git a/openedx/core/djangoapps/course_groups/views.py b/openedx/core/djangoapps/course_groups/views.py index e6cc061e3d..373991b57e 100644 --- a/openedx/core/djangoapps/course_groups/views.py +++ b/openedx/core/djangoapps/course_groups/views.py @@ -7,7 +7,7 @@ from django.views.decorators.http import require_POST from django.contrib.auth.models import User from django.core.paginator import Paginator, EmptyPage from django.core.urlresolvers import reverse -from django.http import Http404, HttpResponse, HttpResponseBadRequest +from django.http import Http404, HttpResponseBadRequest from django.views.decorators.http import require_http_methods from util.json_request import expect_json, JsonResponse from django.contrib.auth.decorators import login_required diff --git a/openedx/core/djangoapps/credit/api/eligibility.py b/openedx/core/djangoapps/credit/api/eligibility.py index 9a64d69c44..91aa3f79e4 100644 --- a/openedx/core/djangoapps/credit/api/eligibility.py +++ b/openedx/core/djangoapps/credit/api/eligibility.py @@ -6,6 +6,7 @@ whether a user has satisfied those requirements. import logging from openedx.core.djangoapps.credit.exceptions import InvalidCreditRequirements, InvalidCreditCourse +from openedx.core.djangoapps.credit.email_utils import send_credit_notifications from openedx.core.djangoapps.credit.models import ( CreditCourse, CreditRequirement, @@ -13,6 +14,8 @@ from openedx.core.djangoapps.credit.models import ( CreditEligibility, ) +from opaque_keys.edx.keys import CourseKey + log = logging.getLogger(__name__) @@ -155,12 +158,14 @@ def is_user_eligible_for_credit(username, course_key): return CreditEligibility.is_user_eligible_for_credit(course_key, username) -def get_eligibilities_for_user(username): +def get_eligibilities_for_user(username, course_key=None): """ - Retrieve all courses for which the user is eligible for credit. + Retrieve all courses or particular course for which the user is eligible + for credit. Arguments: username (unicode): Identifier of the user. + course_key (unicode): Identifier of the course. Example: >>> get_eligibilities_for_user("ron") @@ -179,12 +184,17 @@ def get_eligibilities_for_user(username): Returns: list """ + eligibilities = CreditEligibility.get_user_eligibilities(username) + if course_key: + course_key = CourseKey.from_string(unicode(course_key)) + eligibilities = eligibilities.filter(course__course_key=course_key) + return [ { - "course_key": eligibility.course.course_key, + "course_key": unicode(eligibility.course.course_key), "deadline": eligibility.deadline, } - for eligibility in CreditEligibility.get_user_eligibilities(username) + for eligibility in eligibilities ] @@ -266,7 +276,12 @@ def set_credit_requirement_status(username, course_key, req_namespace, req_name, # If we're marking this requirement as "satisfied", there's a chance # that the user has met all eligibility requirements. if status == "satisfied": - CreditEligibility.update_eligibility(reqs, username, course_key) + is_eligible, eligibility_record_created = CreditEligibility.update_eligibility(reqs, username, course_key) + if eligibility_record_created and is_eligible: + try: + send_credit_notifications(username, course_key) + except Exception: # pylint: disable=broad-except + log.error("Error sending email") def get_credit_requirement_status(course_key, username, namespace=None, name=None): @@ -285,6 +300,7 @@ def get_credit_requirement_status(course_key, username, namespace=None, name=Non "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid", "display_name": "In Course Reverification", "criteria": {}, + "reason": {}, "status": "failed", "status_date": "2015-06-26 07:49:13", }, @@ -293,6 +309,7 @@ def get_credit_requirement_status(course_key, username, namespace=None, name=Non "name": "i4x://edX/DemoX/proctoring-block/final_uuid", "display_name": "Proctored Mid Term Exam", "criteria": {}, + "reason": {}, "status": "satisfied", "status_date": "2015-06-26 11:07:42", }, @@ -301,7 +318,8 @@ def get_credit_requirement_status(course_key, username, namespace=None, name=Non "name": "i4x://edX/DemoX/proctoring-block/final_uuid", "display_name": "Minimum Passing Grade", "criteria": {"min_grade": 0.8}, - "status": "failed", + "reason": {"final_grade": 0.95}, + "status": "satisfied", "status_date": "2015-06-26 11:07:44", }, ] @@ -320,6 +338,7 @@ def get_credit_requirement_status(course_key, username, namespace=None, name=Non "name": requirement.name, "display_name": requirement.display_name, "criteria": requirement.criteria, + "reason": requirement_status.reason if requirement_status else None, "status": requirement_status.status if requirement_status else None, "status_date": requirement_status.modified if requirement_status else None, }) diff --git a/openedx/core/djangoapps/credit/api/provider.py b/openedx/core/djangoapps/credit/api/provider.py index 6048424b36..00aa1c680e 100644 --- a/openedx/core/djangoapps/credit/api/provider.py +++ b/openedx/core/djangoapps/credit/api/provider.py @@ -8,6 +8,7 @@ import pytz import uuid from django.db import transaction +from lms.djangoapps.django_comment_client.utils import JsonResponse from openedx.core.djangoapps.credit.exceptions import ( UserIsNotEligible, @@ -30,26 +31,39 @@ from util.date_utils import to_timestamp log = logging.getLogger(__name__) -def get_credit_providers(): +def get_credit_providers(providers_list=None): + """Retrieve all available credit providers or filter on given providers_list. + + Arguments: + providers_list (list of strings or None): contains list of ids of credit providers + or None. + + Returns: + list of credit providers represented as dictionaries + Response Values: + >>> get_credit_providers(['hogwarts']) + [ + { + "id": "hogwarts", + "name": "Hogwarts School of Witchcraft and Wizardry", + "url": "https://credit.example.com/", + "status_url": "https://credit.example.com/status/", + "description: "A new model for the Witchcraft and Wizardry School System.", + "enable_integration": false, + "fulfillment_instructions": " +

In order to fulfill credit, Hogwarts School of Witchcraft and Wizardry requires learners to:

+
    +
  • Sample instruction abc
  • +
  • Sample instruction xyz
  • +
", + }, + ... + ] """ - Retrieve all available credit providers. - - Example: - >>> get_credit_providers() - [ - { - "id": "hogwarts", - "display_name": "Hogwarts School of Witchcraft and Wizardry" - }, - ... - ] - - Returns: list - """ - return CreditProvider.get_credit_providers() + return CreditProvider.get_credit_providers(providers_list=providers_list) -def get_credit_provider_info(provider_id): +def get_credit_provider_info(request, provider_id): # pylint: disable=unused-argument """Retrieve the 'CreditProvider' model data against provided credit provider. @@ -89,7 +103,7 @@ def get_credit_provider_info(provider_id): "fulfillment_instructions": credit_provider.fulfillment_instructions } - return credit_provider_data + return JsonResponse(credit_provider_data) @transaction.commit_on_success diff --git a/openedx/core/djangoapps/credit/email_utils.py b/openedx/core/djangoapps/credit/email_utils.py new file mode 100644 index 0000000000..d3dd58ff38 --- /dev/null +++ b/openedx/core/djangoapps/credit/email_utils.py @@ -0,0 +1,150 @@ +""" +This file contains utility functions which will responsible for sending emails. +""" + +import os + +import logging +import pynliner +import urlparse +import uuid + +from django.conf import settings +from django.contrib.auth.models import User +from django.contrib.staticfiles import finders +from django.core.cache import cache +from django.core.mail import EmailMessage +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ + +from email.mime.image import MIMEImage +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from eventtracking import tracker + +from edxmako.shortcuts import render_to_string +from microsite_configuration import microsite +from xmodule.modulestore.django import modulestore + + +log = logging.getLogger(__name__) + + +def send_credit_notifications(username, course_key): + """Sends email notification to user on different phases during credit + course e.g., credit eligibility, credit payment etc. + """ + try: + user = User.objects.get(username=username) + except User.DoesNotExist: + log.error('No user with %s exist', username) + return + + course = modulestore().get_course(course_key, depth=0) + course_display_name = course.display_name + branded_logo = dict(title='Logo', path=settings.NOTIFICATION_EMAIL_EDX_LOGO, cid=str(uuid.uuid4())) + tracking_context = tracker.get_tracker().resolve_context() + tracking_id = str(tracking_context.get('user_id')) + client_id = str(tracking_context.get('client_id')) + events = '&t=event&ec=email&ea=open' + tracking_pixel = 'https://www.google-analytics.com/collect?v=1&tid' + tracking_id + '&cid' + client_id + events + dashboard_link = _email_url_parser('dashboard') + credit_course_link = _email_url_parser('courses', "?type=credit") + context = { + 'full_name': user.get_full_name(), + 'platform_name': settings.PLATFORM_NAME, + 'course_name': course_display_name, + 'branded_logo': branded_logo['cid'], + 'dashboard_link': dashboard_link, + 'credit_course_link': credit_course_link, + 'tracking_pixel': tracking_pixel, + } + + # create the root email message + notification_msg = MIMEMultipart('related') + # add 'alternative' part to root email message to encapsulate the plain and + # HTML versions, so message agents can decide which they want to display. + msg_alternative = MIMEMultipart('alternative') + notification_msg.attach(msg_alternative) + # render the credit notification templates + subject = _("Course Credit Eligibility") + + # add alternative plain text message + email_body_plain = render_to_string('credit_notifications/credit_eligibility_email.txt', context) + msg_alternative.attach(MIMEText(email_body_plain, _subtype='plain')) + + # add alternative html message + email_body = cache.get('css-email-body') + if not email_body: + email_body = with_inline_css( + render_to_string("credit_notifications/credit_eligibility_email.html", context) + ) + cache.set('css-email-body', email_body, settings.CREDIT_NOTIFICATION_CACHE_TIMEOUT) + + msg_alternative.attach(MIMEText(email_body, _subtype='html')) + # add images + logo_image = cache.get('attached-logo-email') + if not logo_image: + logo_image = attach_image(branded_logo, 'Header Logo') + if logo_image: + notification_msg.attach(logo_image) + cache.set('attached-logo-email', logo_image, settings.CREDIT_NOTIFICATION_CACHE_TIMEOUT) + + from_address = microsite.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL) + to_address = user.email + + # send the root email message + msg = EmailMessage(subject, None, from_address, [to_address]) + msg.attach(notification_msg) + msg.send() + + +def with_inline_css(html_without_css): + """Returns html with inline css if the css file path exists + else returns html with out the inline css. + """ + css_filepath = settings.NOTIFICATION_EMAIL_CSS + if not css_filepath.startswith('/'): + css_filepath = finders.FileSystemFinder().find(settings.NOTIFICATION_EMAIL_CSS) + + if css_filepath: + with open(css_filepath, "r") as _file: + css_content = _file.read() + + # insert style tag in the html and run pyliner. + html_with_inline_css = pynliner.fromString('' + html_without_css) + return html_with_inline_css + + return html_without_css + + +def attach_image(img_dict, filename): + """ + Attach images in the email headers. + """ + img_path = img_dict['path'] + if not img_path.startswith('/'): + img_path = finders.FileSystemFinder().find(img_path) + + if img_path: + with open(img_path, 'rb') as img: + msg_image = MIMEImage(img.read(), name=os.path.basename(img_path)) + msg_image.add_header('Content-ID', '<{}>'.format(img_dict['cid'])) + msg_image.add_header("Content-Disposition", "inline", filename=filename) + return msg_image + + +def _email_url_parser(url_name, extra_param=None): + """Parse url according to 'SITE_NAME' which will be used in the mail. + + Args: + url_name(str): Name of the url to be parsed + extra_param(str): Any extra parameters to be added with url if any + + Returns: + str + """ + site_name = microsite.get_value('SITE_NAME', settings.SITE_NAME) + dashboard_url_path = reverse(url_name) + extra_param if extra_param else reverse(url_name) + dashboard_link_parts = ("https", site_name, dashboard_url_path, '', '', '') + return urlparse.urlunparse(dashboard_link_parts) diff --git a/openedx/core/djangoapps/credit/migrations/0016_auto__add_field_creditprovider_eligibility_email_message__add_field_cr.py b/openedx/core/djangoapps/credit/migrations/0016_auto__add_field_creditprovider_eligibility_email_message__add_field_cr.py new file mode 100644 index 0000000000..64417e8398 --- /dev/null +++ b/openedx/core/djangoapps/credit/migrations/0016_auto__add_field_creditprovider_eligibility_email_message__add_field_cr.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +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 field 'CreditProvider.eligibility_email_message' + db.add_column('credit_creditprovider', 'eligibility_email_message', + self.gf('django.db.models.fields.TextField')(default=''), + keep_default=False) + + # Adding field 'CreditProvider.receipt_email_message' + db.add_column('credit_creditprovider', 'receipt_email_message', + self.gf('django.db.models.fields.TextField')(default=''), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'CreditProvider.eligibility_email_message' + db.delete_column('credit_creditprovider', 'eligibility_email_message') + + # Deleting field 'CreditProvider.receipt_email_message' + db.delete_column('credit_creditprovider', 'receipt_email_message') + + + 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'}) + }, + 'credit.creditcourse': { + 'Meta': {'object_name': 'CreditCourse'}, + 'course_key': ('xmodule_django.models.CourseKeyField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'credit.crediteligibility': { + 'Meta': {'unique_together': "(('username', 'course'),)", 'object_name': 'CreditEligibility'}, + 'course': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'eligibilities'", 'to': "orm['credit.CreditCourse']"}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'deadline': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2016, 7, 9, 0, 0)'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}) + }, + 'credit.creditprovider': { + 'Meta': {'object_name': 'CreditProvider'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'eligibility_email_message': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'enable_integration': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'fulfillment_instructions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'provider_description': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'provider_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider_status_url': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '200'}), + 'provider_url': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '200'}), + 'receipt_email_message': ('django.db.models.fields.TextField', [], {'default': "''"}) + }, + 'credit.creditrequest': { + 'Meta': {'unique_together': "(('username', 'course', 'provider'),)", 'object_name': 'CreditRequest'}, + 'course': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'credit_requests'", 'to': "orm['credit.CreditCourse']"}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'parameters': ('jsonfield.fields.JSONField', [], {}), + 'provider': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'credit_requests'", 'to': "orm['credit.CreditProvider']"}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '255'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}) + }, + 'credit.creditrequirement': { + 'Meta': {'unique_together': "(('namespace', 'name', 'course'),)", 'object_name': 'CreditRequirement'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'course': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'credit_requirements'", 'to': "orm['credit.CreditCourse']"}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'criteria': ('jsonfield.fields.JSONField', [], {}), + 'display_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'namespace': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'credit.creditrequirementstatus': { + 'Meta': {'unique_together': "(('username', 'requirement'),)", 'object_name': 'CreditRequirementStatus'}, + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'reason': ('jsonfield.fields.JSONField', [], {'default': '{}'}), + 'requirement': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'statuses'", 'to': "orm['credit.CreditRequirement']"}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}) + }, + 'credit.historicalcreditrequest': { + 'Meta': {'ordering': "(u'-history_date', u'-history_id')", 'object_name': 'HistoricalCreditRequest'}, + 'course': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'+'", 'null': 'True', 'on_delete': 'models.DO_NOTHING', 'to': "orm['credit.CreditCourse']"}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + u'history_date': ('django.db.models.fields.DateTimeField', [], {}), + u'history_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + u'history_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + u'history_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'parameters': ('jsonfield.fields.JSONField', [], {}), + 'provider': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'+'", 'null': 'True', 'on_delete': 'models.DO_NOTHING', 'to': "orm['credit.CreditProvider']"}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '255'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}) + }, + 'credit.historicalcreditrequirementstatus': { + 'Meta': {'ordering': "(u'-history_date', u'-history_id')", 'object_name': 'HistoricalCreditRequirementStatus'}, + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + u'history_date': ('django.db.models.fields.DateTimeField', [], {}), + u'history_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + u'history_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + u'history_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'reason': ('jsonfield.fields.JSONField', [], {'default': '{}'}), + 'requirement': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'+'", 'null': 'True', 'on_delete': 'models.DO_NOTHING', 'to': "orm['credit.CreditRequirement']"}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}) + } + } + + complete_apps = ['credit'] \ No newline at end of file diff --git a/openedx/core/djangoapps/credit/models.py b/openedx/core/djangoapps/credit/models.py index dcbf44cb03..11c82d6e13 100644 --- a/openedx/core/djangoapps/credit/models.py +++ b/openedx/core/djangoapps/credit/models.py @@ -111,34 +111,71 @@ class CreditProvider(TimeStampedModel): ) ) + eligibility_email_message = models.TextField( + default="", + help_text=ugettext_lazy( + "Plain text or html content for displaying custom message inside " + "credit eligibility email content which is sent when user has met " + "all credit eligibility requirements." + ) + ) + + receipt_email_message = models.TextField( + default="", + help_text=ugettext_lazy( + "Plain text or html content for displaying custom message inside " + "credit receipt email content which is sent *after* paying to get " + "credit for a credit course." + ) + ) + CREDIT_PROVIDERS_CACHE_KEY = "credit.providers.list" @classmethod - def get_credit_providers(cls): + def get_credit_providers(cls, providers_list=None): """ - Retrieve a list of all credit providers, represented + Retrieve a list of all credit providers or filter on providers_list, represented as dictionaries. + + Arguments: + provider_list (list of strings or None): contains list of ids if required results + to be filtered, None for all providers. + + Returns: + list of providers represented as dictionaries. + """ - # Attempt to retrieve the credit provider list from the cache + # Attempt to retrieve the credit provider list from the cache if provider_list is None # The cache key is invalidated when the provider list is updated # (a post-save signal handler on the CreditProvider model) # This doesn't happen very often, so we would expect a *very* high # cache hit rate. - providers = cache.get(cls.CREDIT_PROVIDERS_CACHE_KEY) - # Cache miss: construct the provider list and save it in the cache - if providers is None: - providers = [ + credit_providers = cache.get(cls.CREDIT_PROVIDERS_CACHE_KEY) + if credit_providers is None: + # Cache miss: construct the provider list and save it in the cache + + credit_providers = CreditProvider.objects.filter(active=True) + + credit_providers = [ { "id": provider.provider_id, "display_name": provider.display_name, + "url": provider.provider_url, "status_url": provider.provider_status_url, + "description": provider.provider_description, + "enable_integration": provider.enable_integration, + "fulfillment_instructions": provider.fulfillment_instructions, } - for provider in CreditProvider.objects.filter(active=True) + for provider in credit_providers ] - cache.set(cls.CREDIT_PROVIDERS_CACHE_KEY, providers) - return providers + cache.set(cls.CREDIT_PROVIDERS_CACHE_KEY, credit_providers) + + if providers_list: + credit_providers = [provider for provider in credit_providers if provider['id'] in providers_list] + + return credit_providers @classmethod def get_credit_provider(cls, provider_id): @@ -460,6 +497,7 @@ class CreditEligibility(TimeStampedModel): username (str): Identifier of the user being updated. course_key (CourseKey): Identifier of the course. + Returns: tuple """ # Check all requirements for the course to determine if the user # is eligible. We need to check all the *requirements* @@ -478,8 +516,11 @@ class CreditEligibility(TimeStampedModel): username=username, course=CreditCourse.objects.get(course_key=course_key), ) + return is_eligible, True except IntegrityError: - pass + return is_eligible, False + else: + return is_eligible, False @classmethod def get_user_eligibilities(cls, username): diff --git a/openedx/core/djangoapps/credit/tests/test_api.py b/openedx/core/djangoapps/credit/tests/test_api.py index 467cc60e0e..1711d6fad7 100644 --- a/openedx/core/djangoapps/credit/tests/test_api.py +++ b/openedx/core/djangoapps/credit/tests/test_api.py @@ -3,11 +3,18 @@ Tests for the API functions in the credit app. """ import datetime import ddt +import json +from mock import patch import pytz +import unittest +from django.conf import settings +from django.core import mail from django.test import TestCase from django.test.utils import override_settings from django.db import connection, transaction +from django.core.urlresolvers import reverse, NoReverseMatch +from unittest import skipUnless from opaque_keys.edx.keys import CourseKey @@ -29,17 +36,21 @@ from openedx.core.djangoapps.credit.models import ( CreditEligibility ) from student.tests.factories import UserFactory +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory TEST_CREDIT_PROVIDER_SECRET_KEY = "931433d583c84ca7ba41784bad3232e6" +from util.testing import UrlResetMixin + @override_settings(CREDIT_PROVIDER_SECRET_KEYS={ "hogwarts": TEST_CREDIT_PROVIDER_SECRET_KEY, "ASU": TEST_CREDIT_PROVIDER_SECRET_KEY, "MIT": TEST_CREDIT_PROVIDER_SECRET_KEY }) -class CreditApiTestBase(TestCase): +class CreditApiTestBase(ModuleStoreTestCase): """ Base class for test cases of the credit API. """ @@ -51,6 +62,14 @@ class CreditApiTestBase(TestCase): PROVIDER_DESCRIPTION = "A new model for the Witchcraft and Wizardry School System." ENABLE_INTEGRATION = True FULFILLMENT_INSTRUCTIONS = "Sample fulfillment instruction for credit completion." + USER_INFO = { + "username": "bob", + "email": "bob@example.com", + "password": "test_bob", + "full_name": "Bob", + "mailing_address": "123 Fake Street, Cambridge MA", + "country": "US", + } def setUp(self, **kwargs): super(CreditApiTestBase, self).setUp() @@ -73,6 +92,7 @@ class CreditApiTestBase(TestCase): return credit_course +@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') @ddt.ddt class CreditRequirementApiTests(CreditApiTestBase): """ @@ -298,6 +318,8 @@ class CreditRequirementApiTests(CreditApiTestBase): def test_satisfy_all_requirements(self): # Configure a course with two credit requirements self.add_credit_course() + CourseFactory.create(org='edX', number='DemoX', display_name='Demo_Course') + requirements = [ { "namespace": "grade", @@ -316,10 +338,12 @@ class CreditRequirementApiTests(CreditApiTestBase): ] api.set_credit_requirements(self.course_key, requirements) + user = UserFactory.create(username=self.USER_INFO['username'], password=self.USER_INFO['password']) + # Satisfy one of the requirements, but not the other with self.assertNumQueries(7): api.set_credit_requirement_status( - "bob", + user.username, self.course_key, requirements[0]["namespace"], requirements[0]["name"] @@ -329,7 +353,7 @@ class CreditRequirementApiTests(CreditApiTestBase): self.assertFalse(api.is_user_eligible_for_credit("bob", self.course_key)) # Satisfy the other requirement - with self.assertNumQueries(10): + with self.assertNumQueries(11): api.set_credit_requirement_status( "bob", self.course_key, @@ -340,6 +364,10 @@ class CreditRequirementApiTests(CreditApiTestBase): # Now the user should be eligible self.assertTrue(api.is_user_eligible_for_credit("bob", self.course_key)) + # Credit eligible mail should be sent + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].subject, 'Course Credit Eligibility') + # The user should remain eligible even if the requirement status is later changed api.set_credit_requirement_status( "bob", @@ -440,7 +468,11 @@ class CreditProviderIntegrationApiTests(CreditApiTestBase): { "id": self.PROVIDER_ID, "display_name": self.PROVIDER_NAME, + "url": self.PROVIDER_URL, "status_url": self.PROVIDER_STATUS_URL, + "description": self.PROVIDER_DESCRIPTION, + "enable_integration": self.ENABLE_INTEGRATION, + "fulfillment_instructions": self.FULFILLMENT_INSTRUCTIONS } ]) @@ -452,25 +484,25 @@ class CreditProviderIntegrationApiTests(CreditApiTestBase): result = api.get_credit_providers() self.assertEqual(result, []) - def test_get_credit_provider_details(self): + def test_get_credit_providers_details(self): """Test that credit api method 'test_get_credit_provider_details' returns dictionary data related to provided credit provider. """ - expected_result = { - "provider_id": self.PROVIDER_ID, + expected_result = [{ + "id": self.PROVIDER_ID, "display_name": self.PROVIDER_NAME, - "provider_url": self.PROVIDER_URL, - "provider_status_url": self.PROVIDER_STATUS_URL, - "provider_description": self.PROVIDER_DESCRIPTION, + "url": self.PROVIDER_URL, + "status_url": self.PROVIDER_STATUS_URL, + "description": self.PROVIDER_DESCRIPTION, "enable_integration": self.ENABLE_INTEGRATION, - "fulfillment_instructions": self.FULFILLMENT_INSTRUCTIONS - } - result = api.get_credit_provider_info(self.PROVIDER_ID) + "fulfillment_instructions": self.FULFILLMENT_INSTRUCTIONS, + }] + result = api.get_credit_providers([self.PROVIDER_ID]) self.assertEqual(result, expected_result) # now test that user gets empty dict for non existent credit provider - result = api.get_credit_provider_info('fake_provider_id') - self.assertEqual(result, {}) + result = api.get_credit_providers(['fake_provider_id']) + self.assertEqual(result, []) def test_credit_request(self): # Initiate a credit request @@ -687,3 +719,117 @@ class CreditProviderIntegrationApiTests(CreditApiTestBase): """Check the user's credit status. """ statuses = api.get_credit_requests_for_user(self.USER_INFO["username"]) self.assertEqual(statuses[0]["status"], expected_status) + + +class CreditApiFeatureFlagTest(UrlResetMixin, TestCase): + """ + Base class to test the credit api urls. + """ + def setUp(self, **kwargs): + enable_credit_api = kwargs.get('enable_credit_api', False) + with patch.dict('django.conf.settings.FEATURES', {'ENABLE_CREDIT_API': enable_credit_api}): + super(CreditApiFeatureFlagTest, self).setUp('lms.urls') + + +@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') +class CreditApiFeatureFlagDisabledTests(CreditApiFeatureFlagTest): + """ + Test Python API for credit provider api with feature flag + 'ENABLE_CREDIT_API' disabled. + """ + PROVIDER_ID = "hogwarts" + + def setUp(self): + super(CreditApiFeatureFlagDisabledTests, self).setUp(enable_credit_api=False) + + def test_get_credit_provider_details(self): + """ + Test that 'get_provider_info' api url not found. + """ + with self.assertRaises(NoReverseMatch): + reverse('credit:get_provider_info', args=[self.PROVIDER_ID]) + + +@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') +class CreditApiFeatureFlagEnabledTests(CreditApiFeatureFlagTest, CreditApiTestBase): + """ + Test Python API for credit provider api with feature flag + 'ENABLE_CREDIT_API' enabled. + """ + USER_INFO = { + "username": "bob", + "email": "bob@example.com", + "full_name": "Bob", + "mailing_address": "123 Fake Street, Cambridge MA", + "country": "US", + } + + FINAL_GRADE = 0.95 + + def setUp(self): + super(CreditApiFeatureFlagEnabledTests, self).setUp(enable_credit_api=True) + self.user = UserFactory( + username=self.USER_INFO['username'], + email=self.USER_INFO['email'], + ) + + self.user.profile.name = self.USER_INFO['full_name'] + self.user.profile.mailing_address = self.USER_INFO['mailing_address'] + self.user.profile.country = self.USER_INFO['country'] + self.user.profile.save() + + # By default, configure the database so that there is a single + # credit requirement that the user has satisfied (minimum grade) + self._configure_credit() + + def test_get_credit_provider_details(self): + """Test that credit api method 'test_get_credit_provider_details' + returns dictionary data related to provided credit provider. + """ + expected_result = { + "provider_id": self.PROVIDER_ID, + "display_name": self.PROVIDER_NAME, + "provider_url": self.PROVIDER_URL, + "provider_status_url": self.PROVIDER_STATUS_URL, + "provider_description": self.PROVIDER_DESCRIPTION, + "enable_integration": self.ENABLE_INTEGRATION, + "fulfillment_instructions": self.FULFILLMENT_INSTRUCTIONS, + } + path = reverse('credit:get_provider_info', kwargs={'provider_id': self.PROVIDER_ID}) + result = self.client.get(path) + result = json.loads(result.content) + self.assertEqual(result, expected_result) + + # now test that user gets empty dict for non existent credit provider + path = reverse('credit:get_provider_info', kwargs={'provider_id': 'fake_provider_id'}) + result = self.client.get(path) + result = json.loads(result.content) + self.assertEqual(result, {}) + + def _configure_credit(self): + """ + Configure a credit course and its requirements. + + By default, add a single requirement (minimum grade) + that the user has satisfied. + + """ + credit_course = self.add_credit_course() + requirement = CreditRequirement.objects.create( + course=credit_course, + namespace="grade", + name="grade", + active=True + ) + status = CreditRequirementStatus.objects.create( + username=self.USER_INFO["username"], + requirement=requirement, + ) + status.status = "satisfied" + status.reason = {"final_grade": self.FINAL_GRADE} + status.save() + + CreditEligibility.objects.create( + username=self.USER_INFO['username'], + course=CreditCourse.objects.get(course_key=self.course_key) + ) diff --git a/openedx/core/djangoapps/credit/tests/test_signals.py b/openedx/core/djangoapps/credit/tests/test_signals.py index 8499a9267d..f6013f6e25 100644 --- a/openedx/core/djangoapps/credit/tests/test_signals.py +++ b/openedx/core/djangoapps/credit/tests/test_signals.py @@ -6,7 +6,9 @@ import pytz import ddt from datetime import timedelta, datetime +from django.conf import settings from django.test.client import RequestFactory +from unittest import skipUnless from openedx.core.djangoapps.credit.api import ( set_credit_requirements, get_credit_requirement_status @@ -19,6 +21,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory +@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') @ddt.ddt class TestMinGradedRequirementStatus(ModuleStoreTestCase): """Test cases to check the minimum grade requirement status updated. diff --git a/openedx/core/djangoapps/credit/urls.py b/openedx/core/djangoapps/credit/urls.py index 7d7282c91d..01efc405fe 100644 --- a/openedx/core/djangoapps/credit/urls.py +++ b/openedx/core/djangoapps/credit/urls.py @@ -3,20 +3,41 @@ URLs for the credit app. """ from django.conf.urls import patterns, url -from .views import create_credit_request, credit_provider_callback +from .api.provider import get_credit_provider_info +from .views import create_credit_request, credit_provider_callback, get_providers_detail, get_eligibility_for_user + +PROVIDER_ID_PATTERN = r'(?P[^/]+)' urlpatterns = patterns( '', url( - r"^v1/provider/(?P[^/]+)/request/$", + r"^v1/providers/(?P[^/]+)/$", + get_credit_provider_info, + name="get_provider_info" + ), + url( + r"^v1/providers/$", + get_providers_detail, + name="providers_detail" + ), + + url( + r"^v1/providers/{provider_id}/request/$".format(provider_id=PROVIDER_ID_PATTERN), create_credit_request, name="create_request" ), url( - r"^v1/provider/(?P[^/]+)/callback/?$", + r"^v1/providers/{provider_id}/callback/?$".format(provider_id=PROVIDER_ID_PATTERN), credit_provider_callback, name="provider_callback" ), + + url( + r"^v1/eligibility/$", + get_eligibility_for_user, + name="eligibility_details" + ), + ) diff --git a/openedx/core/djangoapps/credit/views.py b/openedx/core/djangoapps/credit/views.py index 9e4506f361..94ef0df283 100644 --- a/openedx/core/djangoapps/credit/views.py +++ b/openedx/core/djangoapps/credit/views.py @@ -12,7 +12,7 @@ from django.http import ( HttpResponseForbidden, Http404 ) -from django.views.decorators.http import require_POST +from django.views.decorators.http import require_POST, require_GET from django.views.decorators.csrf import csrf_exempt from django.conf import settings @@ -29,6 +29,54 @@ from openedx.core.djangoapps.credit.exceptions import CreditApiBadRequest, Credi log = logging.getLogger(__name__) +@require_GET +def get_providers_detail(request): + """ + + **User Cases** + + Returns details of the credit providers filtered by provided query parameters. + + **Parameters:** + + * provider_id (list of provider ids separated with ","): The identifiers for the providers for which + user requested + + **Example Usage:** + + GET /api/credit/v1/providers?provider_id=asu,hogwarts + "response": [ + "id": "hogwarts", + "display_name": "Hogwarts School of Witchcraft and Wizardry", + "url": "https://credit.example.com/", + "status_url": "https://credit.example.com/status/", + "description": "A new model for the Witchcraft and Wizardry School System.", + "enable_integration": false, + "fulfillment_instructions": " +

In order to fulfill credit, Hogwarts School of Witchcraft and Wizardry requires learners to:

+
    +
  • Sample instruction abc
  • +
  • Sample instruction xyz
  • +
", + }, + ... + ] + + **Responses:** + + * 200 OK: The request was created successfully. Returned content + is a JSON-encoded dictionary describing what the client should + send to the credit provider. + + * 404 Not Found: The provider does not exist. + + """ + provider_id = request.GET.get("provider_id", None) + providers_list = provider_id.split(",") if provider_id else None + providers = api.get_credit_providers(providers_list) + return JsonResponse(providers) + + @require_POST def create_credit_request(request, provider_id): """ @@ -44,7 +92,7 @@ def create_credit_request(request, provider_id): **Example Usage:** - POST /api/credit/v1/provider/hogwarts/request/ + POST /api/credit/v1/providers/hogwarts/request/ { "username": "ron", "course_key": "edX/DemoX/Demo_Course" @@ -136,7 +184,7 @@ def credit_provider_callback(request, provider_id): **Example Usage:** - POST /api/credit/v1/provider/{provider-id}/callback + POST /api/credit/v1/providers/{provider-id}/callback { "request_uuid": "557168d0f7664fe59097106c67c3f847", "status": "approved", @@ -200,6 +248,39 @@ def credit_provider_callback(request, provider_id): return HttpResponse() +@require_GET +def get_eligibility_for_user(request): + """ + + **User Cases** + + Retrieve user eligibility against course. + + **Parameters:** + + * course_key (unicode): Identifier of course. + * username (unicode): Username of current User. + + **Example Usage:** + + GET /api/credit/v1/eligibility?username=user&course_key=edX/Demo_101/Fall + "response": { + "course_key": "edX/Demo_101/Fall", + "deadline": "2015-10-23" + } + + **Responses:** + + * 200 OK: The request was created successfully. + + * 404 Not Found: The provider does not exist. + + """ + course_key = request.GET.get("course_key", None) + username = request.GET.get("username", None) + return JsonResponse(api.get_eligibilities_for_user(username=username, course_key=course_key)) + + def _validate_json_parameters(params_string, expected_parameters): """ Load the request parameters as a JSON dictionary and check that diff --git a/openedx/core/djangoapps/profile_images/views.py b/openedx/core/djangoapps/profile_images/views.py index bc51d570d0..c0abce9109 100644 --- a/openedx/core/djangoapps/profile_images/views.py +++ b/openedx/core/djangoapps/profile_images/views.py @@ -29,7 +29,7 @@ LOG_MESSAGE_DELETE = 'Deleted images %(image_names)s for user %(user_id)s' def _make_upload_dt(): """ - Generate a server-side timestamp for the upload. This is in a separate + Generate a server-side timestamp for the upload. This is in a separate function so its behavior can be overridden in tests. """ return datetime.datetime.utcnow().replace(tzinfo=utc) @@ -37,35 +37,36 @@ def _make_upload_dt(): class ProfileImageUploadView(APIView): """ - **Use Cases** + **Use Case** - Upload an image to be used for the user's profile. + * Upload an image for the user's profile. - The requesting user must be signed in. The signed in user can only - upload his or her own profile image. + The requesting user must be signed in. The signed in user can only + upload his or her own profile image. - **Example Requests** + **Example Request** POST /api/profile_images/v1/{username}/upload - **Response for POST** + **Example Responses** - If the requesting user tries to upload the image for a different user: + When the requesting user tries to upload the image for a different user, the + request returns one of the following responses. - * If the requesting user has staff access, the request returns a 403 - error. + * If the requesting user has staff access, the request returns an HTTP 403 + "Forbidden" response. * If the requesting user does not have staff access, the request returns - a 404 error. + an HTTP 404 "Not Found" response. - If no user matches the "username" parameter, the request returns a 404 - error. + * If no user matches the "username" parameter, the request returns an HTTP + 404 "Not Found" response. - If the upload could not be performed, the request returns a 400 error is - with details. + * If the upload could not be performed, the request returns an HTTP 400 "Bad + Request" response with more information. - If the upload is successful, the request returns a 204 status with no - additional content. + * If the upload is successful, the request returns an HTTP 204 "No Content" + response with no additional content. """ parser_classes = (MultiPartParser, FormParser,) @@ -123,34 +124,38 @@ class ProfileImageUploadView(APIView): class ProfileImageRemoveView(APIView): """ - **Use Cases** + **Use Case** - Remove all of the profile images associated with the user's account. + * Remove all of the profile images associated with the user's account. - The requesting user must be signed in. + The requesting user must be signed in. - Users with staff access can remove profile images for other user - accounts. + Users with staff access can remove profile images for other user + accounts. - Users without staff access can only remove their own profile images. + Users without staff access can only remove their own profile images. - **Example Requests** + **Example Request** POST /api/profile_images/v1/{username}/remove - **Response for POST** + **Example Responses** - Requesting users who do not have staff access and try to remove another - user's profile image receive a 404 error. + When the requesting user tries to remove the profile image for a + different user, the request returns one of the following responses. - If no user matches the "username" parameter, the request returns a 404 - error. + * If the user does not have staff access, the request returns an HTTP + 404 "Not Found" response. - If the request could not remove the image, the request returns a 400 - error with details. + * If no user matches the "username" parameter, the request returns an + HTTP 404 "Not Found" response. + + * If the image could not be removed, the request returns an HTTP 400 + "Bad Request" response with more information. + + * If the request successfully removes the image, the request returns + an HTTP 204 "No Content" response with no additional content. - If the request successfully removes the image, the request returns a 204 - status with no additional content. """ authentication_classes = (OAuth2AuthenticationAllowInactiveUser, SessionAuthenticationAllowInactiveUser) diff --git a/openedx/core/djangoapps/user_api/accounts/serializers.py b/openedx/core/djangoapps/user_api/accounts/serializers.py index 9cddc14274..dcca026227 100644 --- a/openedx/core/djangoapps/user_api/accounts/serializers.py +++ b/openedx/core/djangoapps/user_api/accounts/serializers.py @@ -15,7 +15,7 @@ class LanguageProficiencySerializer(serializers.ModelSerializer): Class that serializes the LanguageProficiency model for account information. """ - class Meta: + class Meta(object): # pylint: disable=missing-docstring model = LanguageProficiency fields = ("code",) @@ -36,7 +36,7 @@ class AccountUserSerializer(serializers.HyperlinkedModelSerializer, ReadOnlyFiel """ Class that serializes the portion of User model needed for account information. """ - class Meta: + class Meta(object): # pylint: disable=missing-docstring model = User fields = ("username", "email", "date_joined", "is_active") read_only_fields = ("username", "email", "date_joined", "is_active") @@ -51,7 +51,7 @@ class AccountLegacyProfileSerializer(serializers.HyperlinkedModelSerializer, Rea requires_parental_consent = serializers.SerializerMethodField("get_requires_parental_consent") language_proficiencies = LanguageProficiencySerializer(many=True, allow_add_remove=True, required=False) - class Meta: + class Meta(object): # pylint: disable=missing-docstring model = UserProfile fields = ( "name", "gender", "goals", "year_of_birth", "level_of_education", "country", diff --git a/openedx/core/djangoapps/user_api/accounts/views.py b/openedx/core/djangoapps/user_api/accounts/views.py index 832a890769..e05c937de5 100644 --- a/openedx/core/djangoapps/user_api/accounts/views.py +++ b/openedx/core/djangoapps/user_api/accounts/views.py @@ -27,7 +27,7 @@ class AccountView(APIView): Get or update a user's account information. Updates are supported only through merge patch. - **Example Requests**: + **Example Requests** GET /api/user/v1/accounts/{username}/[?view=shared] @@ -35,29 +35,36 @@ class AccountView(APIView): **Response Values for GET** + If no user exists with the specified username, an HTTP 404 "Not + Found" response is returned. + If the user makes the request for her own account, or makes a - request for another account and has "is_staff" access, the response - contains: - - * username: The username associated with the account. - - * name: The full name of the user. - - * email: email for the user (the new email address must be confirmed - via a confirmation email, so GET will not reflect the change until - the address has been confirmed). + request for another account and has "is_staff" access, an HTTP 200 + "OK" response is returned. The response contains the following + values. + * bio: null or textual representation of user biographical + information ("about me"). + * country: An ISO 3166 country code or null. * date_joined: The date the account was created, in the string format provided by datetime. For example, "2014-08-26T17:52:11Z". - + * email: Email address for the user. New email addresses must be confirmed + via a confirmation email, so GET does not reflect the change until + the address has been confirmed. * gender: One of the following values: - * "m" - * "f" - * "o" * null + * "f" + * "m" + * "o" - * year_of_birth: The year the user was born, as an integer, or null. + * goals: The textual representation of the user's goals, or null. + * is_active: Boolean representation of whether a user is active. + * language: The user's preferred language, or null. + * language_proficiencies: Array of language preferences. Each + preference is a JSON object with the following keys: + + * "code": string ISO 639-1 language code e.g. "en". * level_of_education: One of the following values: @@ -70,86 +77,65 @@ class AccountView(APIView): * "el": Elementary/primary school * "none": None * "o": Other - * null: The user did not enter a value. - - * language: The user's preferred language, or null. - - * country: null (not set), or a Country corresponding to one of the - ISO 3166-1 countries. - - * country: A ISO 3166 country code or null. + * null: The user did not enter a value * mailing_address: The textual representation of the user's mailing address, or null. + * name: The full name of the user. + * profile_image: A JSON representation of a user's profile image + information. This representation has the following keys. - * goals: The textual representation of the user's goals, or null. - - * bio: null or textural representation of user biographical - information ("about me"). - - * is_active: boolean representation of whether a user is active. - - * profile_image: JSON representation of a user's profile image - information. The keys are: the user's profile image: - - * "has_image": boolean indicating whether the user has a profile + * "has_image": Boolean indicating whether the user has a profile image. - - * "image_url_*": absolute URL to various sizes of a user's + * "image_url_*": Absolute URL to various sizes of a user's profile image, where '*' matches a representation of the - corresponding image size such as 'small', 'medium', 'large', - and 'full'. These are configurable via - PROFILE_IMAGE_SIZES_MAP. + corresponding image size, such as 'small', 'medium', 'large', + and 'full'. These are configurable via PROFILE_IMAGE_SIZES_MAP. - * requires_parental_consent: true if the user is a minor - requiring parental consent. + * requires_parental_consent: True if the user is a minor + requiring parental consent. + * username: The username associated with the account. + * year_of_birth: The year the user was born, as an integer, or null. - * language_proficiencies: array of language preferences. Each - preference is a JSON object with the following keys: - - * "code": string ISO 639-1 language code e.g. "en". - - For all text fields, clients rendering the values should take care - to HTML escape them to avoid script injections, as the data is - stored exactly as specified. The intention is that plain text is - supported, not HTML. + For all text fields, plain text instead of HTML is supported. The + data is stored exactly as specified. Clients must HTML escape + rendered values to avoid script injections. If a user who does not have "is_staff" access requests account information for a different user, only a subset of these fields is - returned. The fields returned depend on the configuration setting - ACCOUNT_VISIBILITY_CONFIGURATION, and the visibility preference of the - user for whom data is requested. + returned. The returns fields depend on the + ACCOUNT_VISIBILITY_CONFIGURATION configuration setting and the + visibility preference of the user for whom data is requested. - Note that a user can view which account fields they have shared with - other users by requesting their own username and providing the url - parameter "view=shared". - - If no user exists with the specified username, a 404 error is - returned. + Note that a user can view which account fields they have shared + with other users by requesting their own username and providing + the "view=shared" URL parameter. **Response Values for PATCH** Users can only modify their own account information. If the - requesting user does not have username "username", this method will - return with a status of 403 for staff access but a 404 for ordinary - users to avoid leaking the existence of the account. + requesting user does not have the specified username and has staff + access, the request returns an HTTP 403 "Forbidden" response. If + the requesting user does not have staff access, the request + returns an HTTP 404 "Not Found" response to avoid revealing the + existence of the account. - If no user exists with the specified username, a 404 error is - returned. + If no user exists with the specified username, an HTTP 404 "Not + Found" response is returned. - If "application/merge-patch+json" is not the specified content type, - a 415 error is returned. + If "application/merge-patch+json" is not the specified content + type, a 415 "Unsupported Media Type" response is returned. - If the update could not be completed due to validation errors, this - method returns a 400 error with all error messages in the - "field_errors" field of the returned JSON. + If validation errors prevent the update, this method returns a 400 + "Bad Request" response that includes a "field_errors" field that + lists all error messages. - If the update could not be completed due to a failure at the time of - the update, a 400 error is returned with specific errors in the - returned JSON collection. + If a failure at the time of the update prevents the update, a 400 + "Bad Request" error is returned. The JSON collection contains + specific errors. - If the update is successful, a 204 status is returned with no - additional content. + If the update is successful, an HTTP 204 "No Content" response is + returned with no additional content. """ authentication_classes = (OAuth2AuthenticationAllowInactiveUser, SessionAuthenticationAllowInactiveUser) permission_classes = (permissions.IsAuthenticated,) diff --git a/openedx/core/djangoapps/user_api/forms.py b/openedx/core/djangoapps/user_api/forms.py index 8dd6130623..0dd0456e83 100644 --- a/openedx/core/djangoapps/user_api/forms.py +++ b/openedx/core/djangoapps/user_api/forms.py @@ -1,2 +1,3 @@ +# pylint: disable=unused-import, missing-docstring # TODO: eventually move this implementation into the user_api from student.forms import PasswordResetFormNoActive diff --git a/openedx/core/djangoapps/user_api/management/tests/test_email_opt_in_list.py b/openedx/core/djangoapps/user_api/management/tests/test_email_opt_in_list.py index f3c320c0db..9ea502a166 100644 --- a/openedx/core/djangoapps/user_api/management/tests/test_email_opt_in_list.py +++ b/openedx/core/djangoapps/user_api/management/tests/test_email_opt_in_list.py @@ -7,14 +7,11 @@ import csv from collections import defaultdict from unittest import skipUnless - import ddt from django.conf import settings -from django.test.utils import override_settings from django.core.management.base import CommandError - -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, mixed_store_config +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory from student.models import CourseEnrollment diff --git a/openedx/core/djangoapps/user_api/models.py b/openedx/core/djangoapps/user_api/models.py index 0409f8d9c2..0fd22ac83d 100644 --- a/openedx/core/djangoapps/user_api/models.py +++ b/openedx/core/djangoapps/user_api/models.py @@ -1,7 +1,7 @@ from django.contrib.auth.models import User from django.core.validators import RegexValidator from django.db import models -from django.db.models.signals import pre_delete, post_delete, pre_save, post_save +from django.db.models.signals import post_delete, pre_save, post_save from django.dispatch import receiver from model_utils.models import TimeStampedModel @@ -24,7 +24,7 @@ class UserPreference(models.Model): key = models.CharField(max_length=255, db_index=True, validators=[RegexValidator(KEY_REGEX)]) value = models.TextField() - class Meta: # pylint: disable=missing-docstring + class Meta(object): # pylint: disable=missing-docstring unique_together = ("user", "key") @classmethod @@ -93,7 +93,7 @@ class UserCourseTag(models.Model): course_id = CourseKeyField(max_length=255, db_index=True) value = models.TextField() - class Meta: # pylint: disable=missing-docstring + class Meta(object): # pylint: disable=missing-docstring unique_together = ("user", "course_id", "key") @@ -108,6 +108,6 @@ class UserOrgTag(TimeStampedModel): org = models.CharField(max_length=255, db_index=True) value = models.TextField() - class Meta: + class Meta(object): """ Meta class for defining unique constraints. """ unique_together = ("user", "org", "key") diff --git a/openedx/core/djangoapps/user_api/preferences/views.py b/openedx/core/djangoapps/user_api/preferences/views.py index 7070d20c73..d86ca28e68 100644 --- a/openedx/core/djangoapps/user_api/preferences/views.py +++ b/openedx/core/djangoapps/user_api/preferences/views.py @@ -1,5 +1,6 @@ """ -NOTE: this API is WIP and has not yet been approved. Do not use this API without talking to Christina or Andy. +NOTE: this API is WIP and has not yet been approved. Do not use this API +without talking to Christina or Andy. For more information, see: https://openedx.atlassian.net/wiki/display/TNL/User+API @@ -28,60 +29,62 @@ class PreferencesView(APIView): """ **Use Cases** - Get or update the user's preference information. Updates are only supported through merge patch. - Preference values of null in a patch request are treated as requests to remove the preference. + Get or update the user's preference information. Updates are only + supported through merge patch. Preference values of null in a + patch request are treated as requests to remove the preference. - **Example Requests**: + **Example Requests** GET /api/user/v1/preferences/{username}/ PATCH /api/user/v1/preferences/{username}/ with content_type "application/merge-patch+json" - **Response Value for GET** + **Response Values for GET** + + If no user exists with the specified username, an HTTP 404 "Not + Found" response is returned. + + If a user without "is_staff" access requests preferences for a + different user, an HTTP 404 "Not Found" message is returned. If the user makes the request for her own account, or makes a - request for another account and has "is_staff" access, the response - contains a JSON dictionary with a key/value pair (of type String) - for each preference. + request for another account and has "is_staff" access, an HTTP 200 + "OK" response is returned. The response contains a JSON dictionary + with a key/value pair (of type String) for each preference. The list of preferences depends on your implementation. By default, - preferences include: + the list includes the following preferences. + * account_privacy: The user's setting for sharing her personal + profile. Possible values are "all_users" or "private". * pref-lan: The user's preferred language, as set in account settings. - * account_privacy: The user's setting for sharing her personal - profile. Possible values are ``all_users`` or ``private``. + **Response Values for PATCH** - If a user without "is_staff" access requests preferences for a - different user, a 404 error is returned. + Users can only modify their own preferences. If the + requesting user does not have the specified username and has staff + access, the request returns an HTTP 403 "Forbidden" response. If + the requesting user does not have staff access, the request + returns an HTTP 404 "Not Found" response to avoid revealing the + existence of the account. - If the specified username does not exist, a 404 is returned. + If no user exists with the specified username, an HTTP 404 "Not + Found" response is returned. - **Response for PATCH** + If "application/merge-patch+json" is not the specified content + type, a 415 "Unsupported Media Type" response is returned. - Users can only modify their own preferences. If the requesting user - does not have username "username", this method will return with a - status of 403 for users with staff access but a 404 for ordinary - users to avoid leaking the existence of the account. + If validation errors prevent the update, this method returns a 400 + "Bad Request" response that includes a "field_errors" field that + lists all error messages. - This method will also return a 404 if no user exists with username - "username". - - If "application/merge-patch+json" is not the specified content_type, - this method returns a 415 status. - - If the update could not be completed due to validation errors, this - method returns a 400 with all preference-specific error messages in - the "field_errors" field of the returned JSON. - - If the update could not be completed due to failure at the time of - update, this method returns a 400 with specific errors in the - returned JSON. - - If the update is successful, a 204 status is returned with no - additional content. + If a failure at the time of the update prevents the update, a 400 + "Bad Request" error is returned. The JSON collection contains + specific errors. + If the update is successful, an HTTP 204 "No Content" response is + returned with no additional content. """ authentication_classes = (OAuth2AuthenticationAllowInactiveUser, SessionAuthenticationAllowInactiveUser) permission_classes = (permissions.IsAuthenticated, IsUserInUrlOrStaff) @@ -142,7 +145,7 @@ class PreferencesDetailView(APIView): Get, create, update, or delete a specific user preference. - **Example Requests**: + **Example Requests** GET /api/user/v1/preferences/{username}/{preference_key} @@ -152,38 +155,45 @@ class PreferencesDetailView(APIView): **Response Values for GET** - The preference value will be returned as a JSON string. + If the specified username or preference does not exist, an HTTP + 404 "Not Found" response is returned. - If a user without "is_staff" access has requested preferences for a - different user, this method returns a 404. + If a user without "is_staff" access requests preferences for a + different user, a 404 error is returned. - If the specified username or preference does not exist, this method - returns a 404. + If the user makes the request for her own account, or makes a + request for another account and has "is_staff" access, an HTTP 200 + "OK" response is returned that contains a JSON string. **Response Values for PUT** - A successful put returns a 204 and no content. + Users can only modify their own preferences. If the + requesting user does not have the specified username and has staff + access, the request returns an HTTP 403 "Forbidden" response. If + the requesting user does not have staff access, the request + returns an HTTP 404 "Not Found" response to avoid revealing the + existence of the account. - Users can only modify their own preferences. If the requesting user - does not have username "username", this method will return with a - status of 403 for users with staff access but a 404 for ordinary - users to avoid leaking the existence of the account. + If the specified preference does not exist, an HTTP 404 "Not + Found" response is returned. - If the specified preference does not exist, this method returns a - 404. + If the request is successful, a 204 "No Content" status is returned + with no additional content. - **Response for DELETE** + **Response Values for DELETE** - A successful delete returns a 204 and no content. + Users can only delete their own preferences. If the + requesting user does not have the specified username and has staff + access, the request returns an HTTP 403 "Forbidden" response. If + the requesting user does not have staff access, the request + returns an HTTP 404 "Not Found" response to avoid revealing the + existence of the account. - Users can only delete their own preferences. If the requesting user - does not have username "username", this method will return with a - status of 403 for users with staff access but a 404 for ordinary - users to avoid leaking the existence of the account. - - If the specified preference does not exist, this method returns a - 404. + If the specified preference does not exist, an HTTP 404 "Not + Found" response is returned. + If the update is successful, an HTTP 204 "No Content" response is + returned with no additional content. """ authentication_classes = (OAuth2AuthenticationAllowInactiveUser, SessionAuthenticationAllowInactiveUser) permission_classes = (permissions.IsAuthenticated, IsUserInUrlOrStaff) diff --git a/openedx/core/djangoapps/user_api/serializers.py b/openedx/core/djangoapps/user_api/serializers.py index fefee20e53..e95dedee00 100644 --- a/openedx/core/djangoapps/user_api/serializers.py +++ b/openedx/core/djangoapps/user_api/serializers.py @@ -16,7 +16,7 @@ class UserSerializer(serializers.HyperlinkedModelSerializer): def get_preferences(self, user): return dict([(pref.key, pref.value) for pref in user.preferences.all()]) - class Meta: + class Meta(object): # pylint: disable=missing-docstring model = User # This list is the minimal set required by the notification service fields = ("id", "url", "email", "name", "username", "preferences") @@ -26,7 +26,7 @@ class UserSerializer(serializers.HyperlinkedModelSerializer): class UserPreferenceSerializer(serializers.HyperlinkedModelSerializer): user = UserSerializer() - class Meta: + class Meta(object): # pylint: disable=missing-docstring model = UserPreference depth = 1 @@ -36,7 +36,7 @@ class RawUserPreferenceSerializer(serializers.ModelSerializer): """ user = serializers.PrimaryKeyRelatedField() - class Meta: + class Meta(object): # pylint: disable=missing-docstring model = UserPreference depth = 1 diff --git a/openedx/core/djangoapps/user_api/tests/test_models.py b/openedx/core/djangoapps/user_api/tests/test_models.py index 77292f63af..7b4cec224a 100644 --- a/openedx/core/djangoapps/user_api/tests/test_models.py +++ b/openedx/core/djangoapps/user_api/tests/test_models.py @@ -1,5 +1,6 @@ -import json - +""" +Test UserPreferenceModel and UserPreference events +""" from django.db import IntegrityError from django.test import TestCase diff --git a/openedx/core/djangoapps/user_api/tests/test_views.py b/openedx/core/djangoapps/user_api/tests/test_views.py index d07463517a..c857588fcd 100644 --- a/openedx/core/djangoapps/user_api/tests/test_views.py +++ b/openedx/core/djangoapps/user_api/tests/test_views.py @@ -78,7 +78,7 @@ class ApiTestCase(TestCase): """Given a user preference object, get the URI for the corresponding resource""" prefs = self.get_json(USER_PREFERENCE_LIST_URI)["results"] for pref in prefs: - if (pref["user"]["id"] == target_pref.user.id and pref["key"] == target_pref.key): + if pref["user"]["id"] == target_pref.user.id and pref["key"] == target_pref.key: return pref["url"] self.fail() diff --git a/openedx/core/djangoapps/user_api/views.py b/openedx/core/djangoapps/user_api/views.py index 25ac391124..34efebcccd 100644 --- a/openedx/core/djangoapps/user_api/views.py +++ b/openedx/core/djangoapps/user_api/views.py @@ -196,7 +196,7 @@ class RegistrationView(APIView): # Map field names to the instance method used to add the field to the form self.field_handlers = {} - for field_name in (self.DEFAULT_FIELDS + self.EXTRA_FIELDS): + for field_name in self.DEFAULT_FIELDS + self.EXTRA_FIELDS: handler = getattr(self, "_add_{field_name}_field".format(field_name=field_name)) self.field_handlers[field_name] = handler diff --git a/cms/lib/django_require/__init__.py b/openedx/core/lib/django_require/__init__.py similarity index 100% rename from cms/lib/django_require/__init__.py rename to openedx/core/lib/django_require/__init__.py diff --git a/cms/lib/django_require/staticstorage.py b/openedx/core/lib/django_require/staticstorage.py similarity index 100% rename from cms/lib/django_require/staticstorage.py rename to openedx/core/lib/django_require/staticstorage.py diff --git a/pavelib/acceptance_test.py b/pavelib/acceptance_test.py index 31ac46c954..4da81515b1 100644 --- a/pavelib/acceptance_test.py +++ b/pavelib/acceptance_test.py @@ -8,7 +8,7 @@ from optparse import make_option try: from pygments.console import colorize except ImportError: - colorize = lambda color, text: text # pylint: disable-msg=invalid-name + colorize = lambda color, text: text # pylint: disable=invalid-name __test__ = False # do not collect diff --git a/pavelib/bok_choy.py b/pavelib/bok_choy.py index 8fcab25e21..808fc410a1 100644 --- a/pavelib/bok_choy.py +++ b/pavelib/bok_choy.py @@ -12,7 +12,7 @@ import os try: from pygments.console import colorize except ImportError: - colorize = lambda color, text: text # pylint: disable-msg=invalid-name + colorize = lambda color, text: text # pylint: disable=invalid-name __test__ = False # do not collect diff --git a/pavelib/i18n.py b/pavelib/i18n.py index b4a68359a5..a6a67fcdeb 100644 --- a/pavelib/i18n.py +++ b/pavelib/i18n.py @@ -9,7 +9,7 @@ from paver.easy import task, cmdopts, needs, sh try: from pygments.console import colorize except ImportError: - colorize = lambda color, text: text # pylint: disable-msg=invalid-name + colorize = lambda color, text: text # pylint: disable=invalid-name @task diff --git a/pavelib/paver_tests/test_paver_get_quality_reports.py b/pavelib/paver_tests/test_paver_get_quality_reports.py index a1cde45300..1b9f7e83a1 100644 --- a/pavelib/paver_tests/test_paver_get_quality_reports.py +++ b/pavelib/paver_tests/test_paver_get_quality_reports.py @@ -1,12 +1,9 @@ -import os -import tempfile +""" +Tests to ensure only the report files we want are returned as part of run_quality. +""" import unittest -from mock import patch, Mock -from ddt import ddt, file_data - +from mock import patch import pavelib.quality -import paver.easy -from paver.easy import BuildFailure class TestGetReportFiles(unittest.TestCase): diff --git a/pavelib/tests.py b/pavelib/tests.py index 36a188476b..1b8fda1a3e 100644 --- a/pavelib/tests.py +++ b/pavelib/tests.py @@ -3,7 +3,7 @@ Unit test tasks """ import os import sys -from paver.easy import sh, task, cmdopts, needs, call_task, no_help +from paver.easy import sh, task, cmdopts, needs, call_task from pavelib.utils.test import suites from pavelib.utils.envs import Env from optparse import make_option @@ -11,7 +11,7 @@ from optparse import make_option try: from pygments.console import colorize except ImportError: - colorize = lambda color, text: text # pylint: disable-msg=invalid-name + colorize = lambda color, text: text # pylint: disable=invalid-name __test__ = False # do not collect diff --git a/pavelib/utils/test/bokchoy_utils.py b/pavelib/utils/test/bokchoy_utils.py index 686bc515fc..237621a9f0 100644 --- a/pavelib/utils/test/bokchoy_utils.py +++ b/pavelib/utils/test/bokchoy_utils.py @@ -13,7 +13,7 @@ from pavelib.utils.process import run_background_process try: from pygments.console import colorize except ImportError: - colorize = lambda color, text: text # pylint: disable-msg=invalid-name + colorize = lambda color, text: text # pylint: disable=invalid-name __test__ = False # do not collect @@ -80,7 +80,7 @@ def wait_for_server(server, port): if int(response.status) == 200: server_ok = True break - except: # pylint: disable-msg=bare-except + except: # pylint: disable=bare-except pass attempts += 1 diff --git a/pavelib/utils/test/suites/bokchoy_suite.py b/pavelib/utils/test/suites/bokchoy_suite.py index 1301368436..0328ad758a 100644 --- a/pavelib/utils/test/suites/bokchoy_suite.py +++ b/pavelib/utils/test/suites/bokchoy_suite.py @@ -12,7 +12,7 @@ from pavelib.utils.test import utils as test_utils try: from pygments.console import colorize except ImportError: - colorize = lambda color, text: text # pylint: disable-msg=invalid-name + colorize = lambda color, text: text # pylint: disable=invalid-name __test__ = False # do not collect diff --git a/pavelib/utils/test/suites/nose_suite.py b/pavelib/utils/test/suites/nose_suite.py index 901a8efa57..5dab89cdbc 100644 --- a/pavelib/utils/test/suites/nose_suite.py +++ b/pavelib/utils/test/suites/nose_suite.py @@ -2,7 +2,6 @@ Classes used for defining and running nose test suites """ import os -from paver.easy import call_task from pavelib.utils.test import utils as test_utils from pavelib.utils.test.suites.suite import TestSuite from pavelib.utils.envs import Env diff --git a/pavelib/utils/test/suites/suite.py b/pavelib/utils/test/suites/suite.py index bfe83d0766..58b1f841e9 100644 --- a/pavelib/utils/test/suites/suite.py +++ b/pavelib/utils/test/suites/suite.py @@ -10,7 +10,7 @@ from pavelib.utils.process import kill_process try: from pygments.console import colorize except ImportError: - colorize = lambda color, text: text # pylint: disable-msg=invalid-name + colorize = lambda color, text: text # pylint: disable=invalid-name __test__ = False # do not collect diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index efa4f34121..f3f4239b68 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -156,3 +156,6 @@ analytics-python==0.4.4 # Needed for mailchimp(mailing djangoapp) mailsnake==1.6.2 jsonfield==1.0.3 + +# Inlines CSS styles into HTML for email notifications. +pynliner==0.5.2 diff --git a/requirements/edx/github.txt b/requirements/edx/github.txt index d77c1dbd0a..0000d56255 100644 --- a/requirements/edx/github.txt +++ b/requirements/edx/github.txt @@ -44,10 +44,10 @@ git+https://github.com/hmarr/django-debug-toolbar-mongo.git@b0686a76f1ce3532088c -e git+https://github.com/edx/opaque-keys.git@27dc382ea587483b1e3889a3d19cbd90b9023a06#egg=opaque-keys git+https://github.com/edx/ease.git@release-2015-07-14#egg=ease==0.1.3 -e git+https://github.com/edx/i18n-tools.git@v0.1.1#egg=i18n-tools -git+https://github.com/edx/edx-oauth2-provider.git@0.5.4#egg=oauth2-provider==0.5.4 +git+https://github.com/edx/edx-oauth2-provider.git@0.5.5#egg=oauth2-provider==0.5.5 -e git+https://github.com/edx/edx-val.git@v0.0.5#egg=edx-val -e git+https://github.com/pmitros/RecommenderXBlock.git@518234bc354edbfc2651b9e534ddb54f96080779#egg=recommender-xblock --e git+https://github.com/edx/edx-search.git@release-2015-07-03#egg=edx-search +-e git+https://github.com/edx/edx-search.git@release-2015-07-22#egg=edx-search -e git+https://github.com/edx/edx-milestones.git@release-2015-06-17#egg=edx-milestones git+https://github.com/edx/edx-lint.git@ed8c8d2a0267d4d42f43642d193e25f8bd575d9b#egg=edx_lint==0.2.3 -e git+https://github.com/edx/xblock-utils.git@213a97a50276d6a2504d8133650b2930ead357a0#egg=xblock-utils diff --git a/scripts/all-tests.sh b/scripts/all-tests.sh index 291a89cdb7..35ce75d7bd 100755 --- a/scripts/all-tests.sh +++ b/scripts/all-tests.sh @@ -58,7 +58,7 @@ git clean -qxfd source scripts/jenkins-common.sh # Violations thresholds for failing the build -PYLINT_THRESHOLD=7000 +PYLINT_THRESHOLD=6600 JSHINT_THRESHOLD=3700 # If the environment variable 'SHARD' is not set, default to 'all'. diff --git a/scripts/release.py b/scripts/release.py index 4410d653cd..40440d0b06 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -403,7 +403,7 @@ def generate_pr_table(start_ref, end_ref): """ Return a UTF-8 string corresponding to a pull request table to embed in Confluence. """ - header = "|| Merged By || Author || Title || PR || JIRA || Verified? ||" + header = "|| Merged By || Author || Title || PR || JIRA || Release Notes? || Verified? ||" pr_link = "[#{num}|https://github.com/edx/edx-platform/pull/{num}]" user_link = "[@{user}|https://github.com/{user}]" rows = [header] @@ -424,12 +424,13 @@ def generate_pr_table(start_ref, end_ref): title = "?" body = "?" author = "" - rows.append("| {merged_by} | {author} | {title} | {pull_request} | {jira} | {verified} |".format( + rows.append("| {merged_by} | {author} | {title} | {pull_request} | {jira} | {release_notes} | {verified} |".format( merged_by=email if i == 0 else "", author=user_link.format(user=author) if author else "", title=title.replace("|", "\|").replace('{', '\{').replace('}', '\}'), pull_request=pr_link.format(num=pull_request), jira=", ".join(parse_ticket_references(body)), + release_notes="", verified="", )) return "\n".join(rows).encode("utf8") @@ -455,16 +456,17 @@ def generate_commit_table(start_ref, end_ref): The commits in the table should only be commits that are not in the pull request table. """ - header = "|| Author || Summary || Commit || JIRA || Verified? ||" + header = "|| Author || Summary || Commit || JIRA || Release Notes? || Verified? ||" commit_link = "[commit|https://github.com/edx/edx-platform/commit/{sha}]" rows = [header] commits = get_commits_not_in_prs(start_ref, end_ref) for commit in commits: - rows.append("| {author} | {summary} | {commit} | {jira} | {verified} |".format( + rows.append("| {author} | {summary} | {commit} | {jira} | {release_notes} | {verified} |".format( author=commit.author.email, summary=commit.summary.replace("|", "\|"), commit=commit_link.format(sha=commit.hexsha), jira=", ".join(parse_ticket_references(commit.message)), + release_notes="", verified="", )) return "\n".join(rows)